Skip to content

Commit 0761545

Browse files
committed
Merge commit '77afda7b2aede743abe7f900093ee88ac9f75dff'
2 parents 9a60b2a + 77afda7 commit 0761545

5 files changed

Lines changed: 71 additions & 20 deletions

File tree

QMUI/QMUIKit/UIComponents/QMUIModalPresentationViewController.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ - (void)showWithAnimated:(BOOL)animated completion:(void (^)(BOOL))completion {
393393
self.containerWindow.windowLevel = UIWindowLevelQMUIAlertView;
394394
self.containerWindow.backgroundColor = UIColorClear;// 避免横竖屏旋转时出现黑色
395395
}
396+
self.supportedOrientationMask = [QMUIHelper visibleViewController].supportedInterfaceOrientations;
396397
self.containerWindow.rootViewController = self;
397398
[self.containerWindow makeKeyAndVisible];
398399
}

QMUI/QMUIKit/UIComponents/QMUIZoomImageView.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,22 @@
2525
/**
2626
* 支持缩放查看图片(包括 Live Photo)的控件,默认显示完整图片,可双击查看原始大小,再次双击查看放大后的大小,第三次双击恢复到初始大小。
2727
*
28-
* 支持通过修改 contentMode 来控制图片默认的显示模式,目前仅支持 UIViewContentModeCenter、UIViewContentModeScaleAspectFill、UIViewContentModeScaleAspectFit,默认为 UIViewContentModeCenter。
28+
* 支持通过修改 contentMode 来控制图片默认的显示模式,目前仅支持 UIViewContentModeCenter、UIViewContentModeScaleAspectFill、UIViewContentModeScaleAspectFit,默认为 UIViewContentModeCenter。注意这里的显示模式是基于 viewportRect 而言的而非整个 zoomImageView
29+
* @see viewportRect
2930
*
3031
* QMUIZoomImageView 提供最基础的图片预览和缩放功能以及 loading、错误等状态的展示支持,其他功能请通过继承来实现。
3132
*/
3233
@interface QMUIZoomImageView : UIView <UIScrollViewDelegate>
3334

3435
@property(nonatomic, weak) id<QMUIZoomImageViewDelegate> delegate;
3536

37+
/**
38+
* 比如常见的上传头像预览界面中间有一个用于裁剪的方框,则 viewportRect 必须被设置为这个方框在 zoomImageView 坐标系内的 frame,否则拖拽图片时无法正确限制图片的显示范围
39+
* @note 如果想要图片覆盖整个 viewportRect,将 contentMode 设置为 UIViewContentModeScaleAspectFill 即可
40+
* 如果设置为 CGRectZero 则表示使用默认值,默认值为和整个 zoomImageView 一样大
41+
*/
42+
@property(nonatomic, assign) CGRect viewportRect;
43+
3644
@property(nonatomic, assign) CGFloat maximumZoomScale;
3745

3846
/// 设置当前要显示的图片,会把 livePhoto 相关内容清空,因此注意不要直接通过 imageView.image 来设置图片。

QMUI/QMUIKit/UIComponents/QMUIZoomImageView.m

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,11 @@ - (void)setMaximumZoomScale:(CGFloat)maximumZoomScale {
158158
}
159159

160160
- (CGFloat)minimumZoomScale {
161-
CGRect viewport = self.bounds;
162-
if (CGRectIsEmpty(viewport) || (!self.image && !self.livePhoto)) {
161+
if ((!self.image && !self.livePhoto)) {
163162
return 1;
164163
}
164+
165+
CGRect viewport = [self finalViewportRect];
165166

166167
CGSize imageSize = self.image ? self.image.size : self.livePhoto.size;
167168

@@ -231,30 +232,32 @@ - (CGRect)imageViewRectInZoomImageView {
231232
}
232233

233234
- (void)handleDidEndZooming {
235+
CGRect viewport = [self finalViewportRect];
236+
234237
UIView *imageView = [self currentContentImageView];
235238
CGRect imageViewFrame = (!self.image && !self.livePhoto) ? CGRectZero : [self convertRect:imageView.frame fromView:imageView.superview];
236-
CGSize viewportSize = self.bounds.size;
237239
UIEdgeInsets contentInset = UIEdgeInsetsZero;
238-
if (!CGRectIsEmpty(imageViewFrame) && !CGSizeIsEmpty(viewportSize)) {
239-
if (CGRectGetWidth(imageViewFrame) < viewportSize.width) {
240-
// 用 floor 而不是 flat,是因为 flat 本质上是向上取整,会导致 left + right 比实际的大,然后 scrollView 就认为可滚动了
241-
contentInset.left = contentInset.right = floor((viewportSize.width - CGRectGetWidth(imageViewFrame)) / 2.0);
242-
}
243-
if (CGRectGetHeight(imageViewFrame) < viewportSize.height) {
244-
// 用 floor 而不是 flat,是因为 flat 本质上是向上取整,会导致 top + bottom 比实际的大,然后 scrollView 就认为可滚动了
245-
contentInset.top = contentInset.bottom = floor((viewportSize.height - CGRectGetHeight(imageViewFrame)) / 2.0);
246-
}
247-
}
248-
self.scrollView.contentInset = contentInset;
249-
self.scrollView.contentSize = imageView.frame.size;
250240

251-
if (self.scrollView.contentInset.top > 0) {
252-
self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top);
241+
contentInset.top = CGRectGetMinY(viewport);
242+
contentInset.left = CGRectGetMinX(viewport);
243+
contentInset.right = CGRectGetWidth(self.bounds) - CGRectGetMaxX(viewport);
244+
contentInset.bottom = CGRectGetHeight(self.bounds) - CGRectGetMaxY(viewport);
245+
246+
// 图片 height 比选图框(viewport)的 height 小,这时应该把图片纵向摆放在选图框中间,且不允许上下移动
247+
if (CGRectGetHeight(viewport) > CGRectGetHeight(imageViewFrame)) {
248+
// 用 floor 而不是 flat,是因为 flat 本质上是向上取整,会导致 top + bottom 比实际的大,然后 scrollView 就认为可滚动了
249+
contentInset.top = floor(CGRectGetMidY(viewport) - CGRectGetHeight(imageViewFrame) / 2.0);
250+
contentInset.bottom = floor(CGRectGetHeight(self.bounds) - CGRectGetMidY(viewport) - CGRectGetHeight(imageViewFrame) / 2.0);
253251
}
254252

255-
if (self.scrollView.contentInset.left > 0) {
256-
self.scrollView.contentOffset = CGPointMake(-self.scrollView.contentInset.left, self.scrollView.contentOffset.y);
253+
// 图片 width 比选图框的 width 小,这时应该把图片横向摆放在选图框中间,且不允许左右移动
254+
if (CGRectGetWidth(viewport) > CGRectGetWidth(imageViewFrame)) {
255+
contentInset.left = floor(CGRectGetMidX(viewport) - CGRectGetWidth(imageViewFrame) / 2.0);
256+
contentInset.right = floor(CGRectGetWidth(self.bounds) - CGRectGetMidX(viewport) - CGRectGetWidth(imageViewFrame) / 2.0);
257257
}
258+
259+
self.scrollView.contentInset = contentInset;
260+
self.scrollView.contentSize = imageView.frame.size;
258261
}
259262

260263
- (BOOL)enabledZoomImageView {
@@ -347,4 +350,19 @@ - (void)scrollViewDidZoom:(UIScrollView *)scrollView {
347350
[self handleDidEndZooming];
348351
}
349352

353+
#pragma mark - 工具方法
354+
355+
- (CGRect)finalViewportRect {
356+
CGRect rect = self.viewportRect;
357+
if (CGRectIsEmpty(rect)) {
358+
// 有可能此时还没有走到过 layoutSubviews 因此拿不到正确的 scrollView 的 size,因此这里要强制 layout 一下
359+
if (!CGSizeEqualToSize(self.scrollView.bounds.size, self.bounds.size)) {
360+
[self setNeedsLayout];
361+
[self layoutIfNeeded];
362+
}
363+
rect = CGRectMakeWithSize(self.scrollView.bounds.size);
364+
}
365+
return rect;
366+
}
367+
350368
@end

QMUI/QMUIKit/UIKitExtensions/CALayer+QMUI.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,13 @@
3030
*/
3131
- (void)qmui_removeDefaultAnimations;
3232

33+
/**
34+
* 产生一个适用于做通用分隔线的 layer,高度为 PixelOne,默认会移除动画,并且背景色用 UIColorSeparator
35+
*/
36+
+ (CALayer *)qmui_separatorLayer;
37+
38+
/**
39+
* 产生一个适用于做列表分隔线的 layer,高度为 PixelOne,默认会移除动画,并且背景色用 TableViewSeparatorColor
40+
*/
41+
+ (CALayer *)qmui_separatorLayerForTableView;
3342
@end

QMUI/QMUIKit/UIKitExtensions/CALayer+QMUI.m

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#import "CALayer+QMUI.h"
1010
#import "QMUICommonDefines.h"
11+
#import "QMUIConfiguration.h"
1112

1213
@implementation CALayer (QMUI)
1314

@@ -80,4 +81,18 @@ - (void)qmui_removeDefaultAnimations {
8081
self.actions = actions;
8182
}
8283

84+
+ (CALayer *)qmui_separatorLayer {
85+
CALayer *layer = [CALayer layer];
86+
[layer qmui_removeDefaultAnimations];
87+
layer.backgroundColor = UIColorSeparator.CGColor;
88+
layer.frame = CGRectMake(0, 0, 0, PixelOne);
89+
return layer;
90+
}
91+
92+
+ (CALayer *)qmui_separatorLayerForTableView {
93+
CALayer *layer = [self qmui_separatorLayer];
94+
layer.backgroundColor = TableViewSeparatorColor.CGColor;
95+
return layer;
96+
}
97+
8398
@end

0 commit comments

Comments
 (0)