@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变大,表示放大