// // ZoomableImageView.m // AIIM // // Created by qitewei on 2025/5/21. // #import "ZoomableImageView.h" @implementation ZoomableImageView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupView]; } return self; } - (void)setupView { // 设置滚动视图属性 self.delegate = self; self.showsVerticalScrollIndicator = NO; self.showsHorizontalScrollIndicator = NO; self.decelerationRate = UIScrollViewDecelerationRateFast; // 添加图片视图 _imageView = [[UIImageView alloc] initWithFrame:self.bounds]; _imageView.contentMode = UIViewContentModeScaleAspectFit; _imageView.userInteractionEnabled = YES; [self addSubview:_imageView]; // 添加手势 UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)]; doubleTap.numberOfTapsRequired = 2; [_imageView addGestureRecognizer:doubleTap]; } - (void)setImage:(UIImage *)image { self.imageView.image = image; [self resetZoom]; } - (void)resetZoom { [self layoutImageView]; } - (void)layoutImageView { if (!self.imageView.image) return; CGSize imageSize = self.imageView.image.size; CGSize boundsSize = self.bounds.size; // 1. 计算使宽度匹配屏幕的缩放比例 CGFloat widthScale = boundsSize.width / imageSize.width; // 2. 设置缩放范围 self.minimumZoomScale = widthScale; self.maximumZoomScale = widthScale * 4.0; self.zoomScale = widthScale; // 3. 调整contentSize和imageView的frame [self updateContentSize]; [self centerImageView]; } - (void)updateContentSize { if (!self.imageView.image) return; CGSize imageSize = self.imageView.image.size; CGFloat scale = self.zoomScale; // 内容大小要基于缩放后的尺寸 self.contentSize = CGSizeMake(imageSize.width * scale, imageSize.height * scale); self.imageView.frame = CGRectMake(0, 0, self.contentSize.width, self.contentSize.height); } - (void)centerImageView { CGSize boundsSize = self.bounds.size; CGSize contentSize = self.contentSize; // 计算水平和垂直偏移 CGFloat horizontalInset = MAX(0, (boundsSize.width - contentSize.width) / 2); CGFloat verticalInset = MAX(0, (boundsSize.height - contentSize.height) / 2); // 设置contentInset保持居中 self.contentInset = UIEdgeInsetsMake(verticalInset, horizontalInset, verticalInset, horizontalInset); } #pragma mark - UIScrollViewDelegate - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return self.imageView; } - (void)scrollViewDidZoom:(UIScrollView *)scrollView { [self centerImageView]; } #pragma mark - Gesture Handlers - (void)handleDoubleTap:(UITapGestureRecognizer *)gesture { if (self.zoomScale > self.minimumZoomScale) { [self setZoomScale:self.minimumZoomScale animated:YES]; } else { CGFloat newZoomScale = self.maximumZoomScale; CGPoint touchPoint = [gesture locationInView:self.imageView]; CGFloat w = self.bounds.size.width / newZoomScale; CGFloat h = self.bounds.size.height / newZoomScale; [self zoomToRect:CGRectMake(touchPoint.x - w/2, touchPoint.y - h/2, w, h) animated:YES]; } } - (void)handleSingleTap:(UITapGestureRecognizer *)gesture { // 通知控制器单击事件 if ([self.superview respondsToSelector:@selector(handleSingleTap:)]) { [self.superview performSelector:@selector(handleSingleTap:) withObject:gesture]; } } @end