引导
“ 本文不适合老司机… ”Copyright © PBWln Unauthorized shall not be reproduced.
本文章将介绍 iOS UI控件 详解,最常使用的三大控件之一 UIScrollView,将会分成两篇文章完整的讲述
UIScrollView
的常用属性方法使用(包括优化方面)及注意点 和 实战开发使用场景案例,文章编写周期会长一些,用到那点实用的东西,会及时补充。
本篇文章主要从【 UIScrollView 属性方法注解】学习总结。
在「时间 & 知识 」有限内,总结的文章难免有「未全、不足 」的地方,还望各位好友指出,以提高文章质量。
目录:
- UIScrollView概念
- UIScrollView基本使用(滚动)
- UIScrollView属性与方法
1.属性 & 方法
2.使用格式 & 说明:
3.简明注解:- UIScrollView代理方法
1.滑动代理方法相关
2.缩放代理方法相关
3.部分代理方法简明示例- UIScrollView处理触摸事件原理
- 常见需求示例 & 原理解析
1.导航栏半透明效果
2.控件导航悬停
3.下拉头部图片放大
4.正反无限轮播(3张)重点- UIScrollView底层实现
- 正反无限轮播(2张)
- UIScrollView.h属性和方法
- 期待 & 后续
UIScrollView概念
我还是喜欢先看官方的说明:
上图简明释义:
可以展示比设备屏幕更大区域的内容,我们可以通过手指滑动来查看内容视图(content view
)的每一部分内容,也可以通过手指捏合来对内容视图进行缩放操作。
UIScrollView 是一个非常重要的控件,UITableView
、UICollectionView
和UITextView
等常用控件全部继承自UIScrollView
,而UIWebView
控件内部也是基于UIScrollView
实现的。而UIScrollView
继承自UIView
,至于它可以滚动的原因我下面会有原理说明。
UIScrollView基本使用(滚动)
UIScrollView
的使用很简单,基本使用方式如下 3点:
|
|
- 说明:如果想让
UIScrollView
进行滚动,必须设置可以滚动的范围
UIScrollView属性与方法
属性 & 方法:
|
|
使用格式 & 说明:
|
|
简明注解:
对于 UIScrollView 最重要的属性 contentSize、 contentOffset、 contentInset,要有正确的认知。
这个图很能说明,这三个属性的区别:
解答上面问题:苹果设计的代理属性为什么是weak?
上图注解:
原因:防止造成循环引用
说明:
rootViewController
指针指向控制器对象(每个控制器都有个View
被 强引用)–>UIView
对象(强引用 内部 属性subViews
)–> 子控件数组对象(强引用 假设scr对象在第0位)–>UIScrollView
对象将ViewController
设置为自己的代理(delegate
),所以的用 弱引用 weak。假设没有指针指向这个控制器,而
delegate
(weak弱引用
) 没有强指针引用,控制器就会释放。
UIScrollView代理方法
滑动代理方法相关
|
|
缩放代理方法相关
|
|
部分代理方法简明示例
|
|
UIScrollView处理触摸事件原理
当用户在UIScrollView的一个子视图上按下时,UIScrollView
并不知道用户是想要滑动内容视图还是点击对应子视图,所以在按下的一瞬间,事件UIEvent
从UIApplication
传递到UIScrollView
后,其会先将该事件拦截而不会立即传递给对应的子视图,同时开始一个150ms
的倒计时,并监听用户接下来的行为
当倒计时结束前,如果用户的手指发生了移动,则直接滚动内容视图,不会将该事件传递给对应的子视图;
当倒计时结束时,如果用户的手指位置没有改变,则调用自身的
-touchesShouldBegin:withEvent:inContentView:
方法询问是否将事件传递给对应的子视图(如果返回NO
,则该事件不会传递给对应的子视图,如果返回YES
,则该事件会传递给对应的子视图,默认为YES
)。当事件被传递给子视图后,如果手指位置又发生了移动,则调用自身的
-touchesShouldCancelInContentView:
方法询问是否取消已经传递给子视图的事件。
常见需求示例 & 原理解析
导航栏半透明效果
原理解析:
默认情况下,在有
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
的的变化,当不满足悬停条件时,待悬停控件属于UIScrollView
的子视图,当满足悬停条件时,待悬停控件属于UIScrollView
的父视图的子视图。
|
|
下拉头部图片放大
原理解析:
- 通过
-scrollViewDidScroll:
代理方法跟踪contentOffset
的的变化,根据contentOffset
动态设置图片的缩放比例。
|
|
正反无限轮播(3张)
原理解析:
- 手动滚动:只创建三张图片: leftImageView、centerImageView、rightImageView,定义中间显示页码为 centerPage ,设置初始
self.centerPage = 0;
,而左右图片页码都以 centerPage 表示,通过scrollViewDidEndDecelerating:
方法判断contentOffsest.x
和scrollView.frame.size.width
比较,使改变self.centerPage
的值,然后对应页码滚动取数组中的图片,始终显示中间一张。
- 定时器滚动: 将定时器添加到
Runloop
的NSRunLoopCommonModes
下,触发方法中设置setContentOffset: animated:YES
方法动画结束时调用scrollViewDidEndScrollingAnimation:
(仅当animated
设置为YES
时才调用),这个方法下self.centerPage++;
。OK了
监听图片点击
当图片被点击的时候,我们往往需要执行某些操作,因此需要监听图片的点击,思路如下:
- 1.定义一个
block
属性暴露给外界void(^LNBlock)(NSInteger index)
,(不会block的可以用代理,或者看这里 Block模式详解)。 - 2.设置
centerImageView
的userInteractionEnabled
为YES
。 - 3.给
scrollView
添加一个点击的手势 - 4.在手势方法里调用
block
,并传入图片索引
核心代码
|
|
UIScrollView底层实现
|
|
总结:
UIScrollView 继承自UIView,内部加了手势,之所以可以滑动,是改变了bounds
,若手指向上滑动,y++
,内容就会向上滑动。这样我们也可以用 给UIView
添加个 Pan手势
实现滚动效果。
正反无限轮播(2张)
大致原理:
最底层是一个UIView
,上面有一个UIScrollView
以及UIPageControl
,scrollView
上有两个UIImageView
,imageView
宽高 = scrollview
宽高 = view
宽高;
假设轮播控件的宽度为x高度为y,我们设置scrollview
的contentSize.width
为3x
,并让scrollview
的水平偏移量为x
,既显示最中间内容。
具体细节请移步这里阅读:
轮播两个ImageView实现 http://www.jianshu.com/p/ef03ec7f23b2
正反无限轮播 效果图
期待
- 如果在阅读过程中遇到 error || new ideas,希望你能 messages 我,我会及时改正谢谢。
- 点击右上角的 喜欢 和 订阅Rss 按钮,可以收藏本仓库,并在 Demo 更新时收到邮件通知。