/**
scrollView中的内容滚动就必须要设置: 滚动范围
contentSize : 子控件的大小, 限定滚动的范围
contentSize 在设置的时候, 一定要比scrollView 的size 要大
如果size 中的 宽度 设为 0 , 就表示在 横向中不能滚动
*/
_scrollView.contentSize = self.imageView.frame.size;
/**
Horizontal : 水平
Vertical : 垂直
是否隐藏滚动指示器
*/
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
/**
bounces : 弹簧效果 ,默认是YES 一般是不关闭
*/
_scrollView.bounces = YES;
/**
不设置contentSize的时候, 弹簧效果开启, 依然看不到
即使不设置contentSize , 在水平和垂直方向上依然有弹簧效果
前提是: scrollView.bounces = YES;
alwaysBounceHorizontal
alwaysBounceVertical
*/
_scrollView.alwaysBounceHorizontal = YES;
_scrollView.alwaysBounceVertical = YES;
/**
没有设置contentInset的时候, 拖动后imageView默认会停留在初始位置
contentInset : 拖动后, 会停留在设置 的内边距的位置(imageView边界距离scrollView的边距)
变相的增加了 滚动的范围
top, left, bottom, right
*/
_scrollView.contentInset = UIEdgeInsetsMake(10, 20, 30, 40);
/**
contentOffset : offset 偏移量 , 滚动到了某个位置
*/
_scrollView.contentOffset = CGPointMake
/**
scrollView 不能滚动的原因
1. contentSize 比 scrollView的size 小
2. _scrollView.userInteractionEnabled = NO;
3. _scrollView.scrollEnabled = NO;
*/
// 设置contentOffset的时候, 有动画效果
[_scrollView setContentOffset:offset animated:YES];
// 当scrollView内容滚动的时候就会调用, 只要在滚动就会调用
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"滚动的时候调用 %@",NSStringFromCGPoint(scrollView.contentOffset));
}
// Drag : 拖拽 开始拖拽的时候调用, 是只会调用一遍
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
NSLog(@"开始拖拽的时候调用");
}
// 停止拖拽 , 调用一次(停止减速的时候调用,手动停止的时候调用)
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
NSLog(@"停止拖拽的时候调用");
}
- (void)viewDidLoad {
[super viewDidLoad];
/**
minimumZoomScale; --> 最小的缩小倍数
maximumZoomScale; --> 最大的放大倍数
*/
_scrollView.minimumZoomScale = 0.3;
_scrollView.maximumZoomScale = 3;
// 设置控制器成为scrollView的代理
_scrollView.delegate = self;
}
// 返回的view将被拉伸(缩放)
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return _imageView;
}
// 只要图片在放大/缩小的过程中都会一直调用
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
NSLog(@"scrollViewDidZoom");
}
// 开始缩放的时候调用
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
NSLog(@"scrollViewWillBeginZooming");
}
// 结束的时候调用
// withView: 进行缩放的view
// atScale: 缩放的倍数
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
NSLog(@"scrollViewDidEndZooming");
}
1.==============UISCrollView 在自动布局中的使用注意
//在autolayout下,会在viewDidAppear之前根据subview的constraint重新计算scrollview的contentsize。 这就是为什么,在viewdidload里面手动设置了contentsize没用。因为在后面,会再重新计算一次,前面手动设置的值会被覆盖掉。
// 解决办法就是:
// 1.去除autolayout选项,自己手动设置contentsize
// 2.如果要使用autolayout,要么自己设置完subview的constraint,然后让系统自动根据constraint计算出contentsize。 要么就在viewDidAppear里面自己手动设置contentsize。
self.baseScrollView.contentSize=CGSizeMake(0, self.view.frame.size.height*2-300);//basescrollView的滚动范围
scrollview布局的注意事项:
上下滚动就将UIView的高度约束设置成300(这个高度就是UIScrollView的内容高度: contentSize.height),水平居中就可以了.
4.接下来所有的控件都添加到UIView中即可利用自动布局来设置约束.
问题的关键在于如何给scrollView内部的子控件添加约束.
scrollView内部子控件约束的添加需要遵循两个原则:
1、scrollView内部子控件的尺寸不能以scrollView的尺寸为参照
2、scrollView内部的子控件的约束必须完整
首先,子控件的尺寸不能以scrollView的尺寸为参照,那么我们有两种选择:
- 提供一个具体值的约束(比如200)
- 子控件的尺寸可以参照scrollView以外其它的控件的尺寸(如控制器的view的尺寸)
其次,约束"完整"的意思是说:子控件在水平及竖直方向上的约束要把scrollView"撑满".
也就是说,在水平方向上,我们需要设置:
- 子控件左侧与父控件的距离
- 子控件自身的宽度
- 子控件右侧距父控件的距离.
竖直方向上也一样,要设置:
- 子控件顶部距父控件的距离
- 子控件的高度
- 子控件底部距父控件的距离.
为什么scrollView如此隔路(隔路:特殊,与众不同)呢?
这是因为,scrollView需要根据添加在其内部的子控件的宽高及与四周的距离计算出它的contentSize
.
举个栗子:
一个添加在scrollView内部的imageView的宽高为{80, 50}, imageView距离上左下右的距离分别为:100, 200, 300, 400,那么不需要用代码赋值contentSize,我们就可以打印出scrollView的contentSize为{680, 450}.
如图:
如果理解起来还是有困难,我们可以把scrollView的contentSize的范围想象成一块UIView(上图中的蓝色区域),暂且叫它Container(实际是没有这个东西的).当我们在storyboard或xib中设置子控件与scrollView之间约束时,实际上设置的是子控件与container之间的约束.
也就是说,子控件的约束决定了container的尺寸(contentSize).
这就说明了为什么我们要在水平和竖直方向用约束"撑满".如果不撑满,container不知道它自己应该多大.
也正是因为container的尺寸由子控件的约束决定,所以子控件的尺寸不能再反过来参照container的尺寸.不然你等于我,我等于你,那到底是多少呢?如果你是Xcode你也会抓狂.(再次强调那个container不是真的,只是为了方便理解)
理论部分解释完毕,回到一开始的案例上.
imageView有了上下左右四个约束,还缺少宽高,我们再添加个固定宽高的约束(可以大一点,太小了看不到滚动效果),问题就可以解决了.
强调一下, 用代码给scrollView添加约束(包括使用Masonry的情况)是一样的.
-------------UIScrollView的代理方法-----
/**
在开始拖拽的时候,把计时器停止
invalidate 无效的意思
*/
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 让计时器无效
[self.timer invalidate];
self.timer=nil;
NSLog(@"定时器无效1");
}
//手指离开scrollview的时候
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
NSLog(@"停止拖拽");
}
/**
当停止加速的时候,让计时器开始工作
手指离开scrollView的时候
*/
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
//- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
NSLog(@"停止加速");
[self NSTimers];
}
//正在滚动的时候
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
}
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
NSLog(@"结束滚动");
NSInteger pageIndex=self.headerScroll.contentOffset.x/self.headerScroll.frame.size.width;
self.pageCtrl.currentPage=pageIndex;
}