|
UIScrollView是一个非常重要的控件,其可以展示比设备屏幕更大区域的内容,我们可以通过手指滑动来查看内容视图的每一部分内容,也可以通过手指捏合来对内容视图进行缩放操作,我们每天开发中都不断显式或隐式地与UIScrollView打交道,下面给大家详细介绍UIScrollView控件。
一、UIScrollView控件是什么?
(1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限
(2)当展⽰示的内容较多,超出⼀一个屏幕时,⽤用户可通过滚动⼿手势来查看屏幕以外的内容
(3)普通的UIView不具备滚动功能,不能显⽰示过多的内容
(4)UIScrollView是一个能够滚动的视图控件,可以⽤用来展⽰示⼤大量的内容,并且可以通过滚 动查看所有的内容
(5) 举例:手机上的“设置”、其他⽰示例程序
二、UIScrollView的简单使用
(1)将需要展⽰的内容添加到UIScrollView中
(2)设置UIScrollView的contentSize属性,告诉UIScrollView所有内容的尺⼨寸,也就是告诉 它滚动的范围(能滚多远,滚到哪⾥里是尽头)
注: 本文中所说的"内容视图"在官方文档中称作"content view",表示UIScrollView中可以用来展示内容的部分
三、属性与方法
内容视图相关
|
1
2
3
4
5
6
7
8
9
10
11
|
@property(nonatomic) CGSize contentSize;
@property(nonatomic) UIEdgeInsets contentInset;
@property(nonatomic) CGPoint contentOffset;
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;
|
滑动相关
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@property(nonatomic,getter=isScrollEnabled) BOOL scrollEnabled;
@property(nonatomic, getter=isDirectionalLockEnabled) BOOL directionalLockEnabled;
@property(nonatomic) BOOL scrollsToTop;
@property(nonatomic, getter=isPagingEnabled) BOOL pagingEnabled;
@property(nonatomic) BOOL bounces;
@property(nonatomic) BOOL alwaysBounceHorizontal;
@property(nonatomic) BOOL alwaysBounceVertical;
@property(nonatomic) CGFloat decelerationRate;
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated;
|
指示器相关
|
1
2
3
4
5
6
7
8
9
10
11
12
|
@property(nonatomic) UIScrollViewIndicatorStyle indicatorStyle;
@property(nonatomic) UIEdgeInsets scrollIndicatorInsets;
@property(nonatomic) BOOL showsHorizontalScrollIndicator;
@property(nonatomic) BOOL showsVerticalScrollIndicator;
- (void)flashScrollIndicators;
|
事件相关
UIScrollView处理触摸事件原理
当用户在UIScrollView的一个子视图上按下时,UIScrollView并不知道用户是想要滑动内容视图还是点击对应子视图,所以在按下的一瞬间,事件UIEvent从UIApplication传递到UIScrollView后,其会先将该事件拦截而不会立即传递给对应的子视图,同时开始一个150ms的倒计时,并监听用户接下来的行为
1、当倒计时结束前,如果用户的手指发生了移动,则直接滚动内容视图,不会将该事件传递给对应的子视图;
2、当倒计时结束时,如果用户的手指位置没有改变,则调用自身的-touchesShouldBegin:withEvent:inContentView:方法询问是否将事件传递给对应的子视图(如果返回NO,则该事件不会传递给对应的子视图,如果返回YES,则该事件会传递给对应的子视图,默认为YES)
3、当事件被传递给子视图后,如果手指位置又发生了移动,则调用自身的-touchesShouldCancelInContentView:方法询问是否取消已经传递给子视图的事件
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@property(nonatomic,readonly,getter=isTracking) BOOL tracking;
@property(nonatomic,readonly,getter=isDragging) BOOL dragging;
@property(nonatomic,readonly,getter=isDecelerating) BOOL decelerating;
@property(nonatomic) BOOL delaysContentTouches;
@property(nonatomic) BOOL canCancelContentTouches;
- (BOOL)touchesShouldBegin:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view;
- (BOOL)touchesShouldCancelInContentView:(UIView *)view;
|
缩放相关
当用户使用两个手指进行缩放操作时,我们调整内容视图的偏移量和缩放比例(注: 用户两个手指操作结束后,有可能仍然有一个手指在操作,这时不会将事件传递给子视图)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@property(nonatomic) CGFloat minimumZoomScale;
@property(nonatomic) CGFloat maximumZoomScale;
@property(nonatomic) CGFloat zoomScale;
- (void)setZoomScale:(CGFloat)scale animated:(BOOL)animated;
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated;
@property(nonatomic) BOOL bouncesZoom;
@property(nonatomic,readonly,getter=isZooming) BOOL zooming;
@property(nonatomic,readonly,getter=isZoomBouncing) BOOL zoomBouncing;
|
键盘相关
|
1
2
|
@property(nonatomic) UIScrollViewKeyboardDismissMode keyboardDismissMode;
|
代理
滑动相关
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;
|
缩放相关
|
1
2
3
4
5
6
7
8
9
10
11
|
- (void)scrollViewDidZoom:(UIScrollView *)scrollView;
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view;
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale;
|
常见需求原理解析
导航栏半透明效果
原理解析:
默认情况下,在有UINavigationBar存在时,系统为了防止UIScrollView被遮挡,其contentInset和scrollIndicatorInsets属性都会被设置为UIEdgeInsetsMake(64, 0, 0, 0);在有UITabBar存在时,系统为了防止UIScrollView被遮挡,其contentInset和scrollIndicatorInsets属性都会被设置为UIEdgeInsetsMake(0, 0, 49, 0)
因此,为了使用此种半透明效果,可以直接将UIScrollView的frame设置为整个屏幕的大小
注1: 系统只在UIScrollView是控制器视图的第0个子视图时才会自动修改contentInset和scrollIndicatorInsets属性
注2: 如果不想让系统自动修改contentInset和scrollIndicatorInsets属性,可以设置self.automaticallyAdjustsScrollViewInsets = NO;
控件悬停
原理解析:
方式一: 在悬停位置放置一个与待悬停控件相同的控件,通过-scrollViewDidScroll:代理方法跟踪contentOffset的的变化,当不满足悬停条件时,将该控件hidden属性设置为YES;当满足悬停条件时,将该控件hidden属性设置为NO
方式二: 通过-scrollViewDidScroll:代理方法跟踪contentOffset的的变化,当不满足悬停条件时,待悬停控件属于UIScrollView的子视图,当满足悬停条件时,待悬停控件属于UIScrollView的父视图的子视图
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.y >= 100)
{
CGRect rect = label.frame;
rect.origin.y = 0;
label.frame = rect;
[self.view addSubview:label];
}
else
{
CGRect rect = label.frame;
rect.origin.y = 100;
label.frame = rect;
[scrollView addSubview:label];
}
}
|
下拉头部图片放大
原理解析:
通过-scrollViewDidScroll:代理方法跟踪contentOffset的的变化,根据contentOffset动态设置图片的缩放比例
|
1
2
3
4
5
6
7
8
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scale = 1 - (scrollView.contentOffset.y / 100);
scale = (scale >= 1) ? scale : 1;
scale = (scale <= 2) ? scale : 2;
imageView.transform = CGAffineTransformMakeScale(scale, scale);
}
|
图片无限轮播
原理解析:
在已知图片数组有N个元素前提下,在UIScrollView中创建N+2个UIImageView,其中第1个至第N个图片为真实内容,第0个与第N个一样,第N+1个与第1个一样,通过-scrollViewDidScroll:代理方法跟踪contentOffset的的变化,在滑动到首尾两个图片处直接设置contentOffset到真实图片处即可
总结
以上就是这篇文章的全部内容了,希望本文的内容对各位iOS开发者们能有所帮助,如果有疑问大家可以留言交流。
来源:https://www.cnblogs.com/Free-Thinker/p/13201301.html |