UIScrollView 缩放实现 以及 缩放原理

@interface ViewController () <UIScrollViewDelegate>
{
    UIImageView *_iv;
    UIEdgeInsets _edgeInsets;
}
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    UIScrollView *sv = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:sv];
    //如果iOS的系统是11.0,会有这样一个宏定义“#define __IPHONE_11_0  110000”;如果系统版本低于11.0则没有这个宏定义
#ifdef __IPHONE_11_0
    if (@available(iOS 11.0, *)) {
        // 避免放大后,滑动scrollview产生的 20 inset
        if ([sv respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
            sv.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        }
    }
#endif
    // 设置代理
    sv.delegate = self;
    // 设置最大最小缩放比例
    sv.minimumZoomScale = 0.5;
    sv.maximumZoomScale = 3.0;
    // 设置两指才允许滚动
    sv.panGestureRecognizer.minimumNumberOfTouches = 2;
    // 滑动的弹性
    sv.bounces = NO;

    UIImage *img = [UIImage imageNamed:@"123.JPG"];
    CGSize imgSize = img.size;
    NSLog(@"imageSize--%@", NSStringFromCGSize(img.size));
    UIImageView *iv = [[UIImageView alloc] initWithImage:img];
    [sv addSubview:iv];
    _iv = iv;
    
    // 图床容器的宽和高,这里是scrollview的宽和高
    CGFloat svW = sv.frame.size.width;
    CGFloat svH = sv.frame.size.height;
    // 图床实际需要的宽和高
    CGFloat ivW = 0.0;
    CGFloat ivH = 0.0;
    if (imgSize.height > imgSize.width) {// 高大于宽 长图片
        // 高取sv的高
        ivH = svH;
        ivW = imgSize.width / imgSize.height * ivH;
    }
    else {// 宽大于高 扁图片
        ivW = svW;
        ivH = imgSize.height / imgSize.width * ivW;
    }
    // 记得给图床宽和高 不给宽高的话 初始化的图床宽和高是按照图片的size来的
    iv.frame = CGRectMake(0, 0, ivW, ivH);
    
    // 通过设置contentInsets的方式 来让图床在宽或者高不能填充满父scrollView的宽或者高时 来让iv居中
    CGFloat topInset = (svH - ivH)*0.5;
    CGFloat leftInset = (svW - ivW)*0.5;
    _edgeInsets = UIEdgeInsetsMake(topInset, leftInset, topInset,leftInset);
    sv.contentInset = _edgeInsets;
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return _iv;
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    NSLog(@"%.2f", scrollView.zoomScale);
    CGFloat scale = scrollView.zoomScale;
    CGFloat w = scrollView.frame.size.width;
    CGFloat h = scrollView.frame.size.height;
    CGFloat contentW = scrollView.contentSize.width;
    CGFloat contentH = scrollView.contentSize.height;

    NSLog(@"frame -- %@", NSStringFromCGRect(scrollView.frame));
    NSLog(@"contentSize -- %@", NSStringFromCGSize(scrollView.contentSize));
    if (scale - 1 > 1e-6) {
        scrollView.contentInset = _edgeInsets;
    }
    else {
        // 注意只有当 设置最小比例小于1时才有必要写这块代码
        // 这个是当 缩小比例小于1时,通过设置inset来是的imageView居中,因为通过打印发现imageView始终是跟随contentSize的
        scrollView.contentInset = UIEdgeInsetsMake((h - contentH) * 0.5, (w - contentW) * 0.5, 0, 0);
    }
}

缩放

  • 一旦设置了 scrollView 的 delegate 并且实现了一个简单的代码,scrollView 就能够缩放了
  • 这些代码的本质是在告诉 scrollView 去缩放谁
  • 利用视图层次结构观察缩放后的 scrollView 和 imageView 的 position(center) 和 bounds 的变化
  • 缩放结束后 scrollView 本身的 frame 并没有发生变化
  • 缩放结束后 imageView 本身的 bounds 也没有发生变化
  • 缩放结束后 imageView 的 center 发生了变化
  • 在知道缩放谁了之后,scrollView会在内部通过修改 缩放目标 的 transfrom 实现缩放效果

so.发生缩放的时候,只会改变子控件的center的Position的x和y,通过改变x和y的大小来进行放大和缩小,x,y变大,表示放大


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值