@@ -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
0 commit comments