关于UIStrollview:
UIScrollView无法滚动可能的原因及解决办法:
Ø没有设置contentSize
ØscrollEnabled=NO
Ø没有接收到触摸事件:userInteractionEnabled=NO
Ø没有取消autolayout功能(要想scrollView滚动,在xcode5.x下必须取消autolayout)注意:在xcode6.1下不需要取消自动布局也可以滚动。但是从Xcode7开始系统建议我们使用AutoLayout来布局UIScorllView
•UIScrollView的frame.size与contentSize的区别?
–frame.size指的是:UIScrollView的可视区域的大小,UIScrollView本身的大小
–contentSize指的是:UIScrollView中所包含的内容的大小(要滚动的实际内容的大小)
•把frame.size和contentSize设置都一样了,还能滚动吗?如果contentSize比frame.size小还能滚动吗?
•总结:在UIScrollView的frame.size这么大的范围内,要显示contentSize这么大的内容。是否需要滚动,取决于contentSize是否比frame.size大。
•@property(nonatomic)CGPointcontentOffset;?
•属性含义:–1>当UIScrollView内部的内容滚动时,内容相对于UIScrollView左上角的偏移
–2>另一种理解方式:内容滚动到了什么位置
•通过点击按钮,实现大图自动滚动(修改contentOffset)?
•1.直接实现,直接修改contentOffset没有动画效果
•2.通过UIView的动画方法实现
•3.通过调用UIScrollView的setContentOffset:animated:来实现带动画效果的滚动。
•@property(nonatomic)UIEdgeInsetscontentInset;?
Ø含义:
Ø内容的内边距
Ø设置UIScrollView的内容在拖动以后,内容距离UIScrollView的内边距。(联想按钮的内边距属性:Inset)
Ø另一种思考方式:想象成把内容加大了,在内容本身的周围加了一圈”外边距”。
UIScrollView的其他属性?
•@property(nonatomic)BOOLbounces;
•设置UIScrollView是否需要弹簧效果
•@property(nonatomic,getter=isScrollEnabled)BOOLscrollEnabled;
Ø设置UIScrollView是否能滚动
•@property(nonatomic)BOOLshowsHorizontalScrollIndicator;
Ø是否显示水平滚动条
•@property(nonatomic)BOOLshowsVerticalScrollIndicator;
Ø是否显示垂直滚动条
如何做一个电台参考步骤?
•1>拖拽一个UIScrollView到控制器view,设置该UIScrollView大小与控制器view一致
•2>设置该UIScrollView的背景色为RGB:212,212,212
•3>向UIScrollView中增加内容
•4>设置UIScrollView的contentSize的height为最下面的图片的最大的Y值,width为0(因为横向不滚动)
•提示:某个方向上不希望滚动,则把该方向上的contentSize的值设置为0
•5>向控制器的view中添加一个UIView到最上方,模拟"导航栏”
•注意:直接拖拽UIView到UIScrollView上,就导致UIView随着UIScrollView进行滚动,
这个UIView不属于UIScrollView所以拖拽的时候最好拖拽到Scene(场景)上。在viewDidLoad中设置contentOffset的y值,为-64(设置默认滚动的位置).
•6>在最底部拖拽一个UIView,模拟”底部菜单”,高度为44
•7>设置顶部"导航栏UIView"与 底部"菜单栏UIView"的alpha= 0.7(设置透明度)
•8>设置contentInset属性的top和bottom的值,在滚动后预留一定的内边距
•注意:获取某个控件的最大的Y值:CGRectGetMaxY(self.lastButton.frame);
•9>设置一开始就滚动到某个位置,通过contentOffset属性实现
•注意这里要把y值设置为负数
实现滚动的时候输出当前滚动的位置?
思考:
1.获取当前滚动的位置:scrollView.contentOffset
2.要想实现滚动的时候显示当前滚动的位置,那么就一定要监听滚动事件。
3.问题:如何监听滚动事件?答:通过代理来监听。
监听事件的另外一种方式:代理。之前学过的一种方式是:addTarget的方式。
用户开始拖拽时,调用scrollViewWillBeginDragging:方法
具体滚动到某个位置时,调用scrollViewDidScroll:方法
用户停止拖拽时,调用scrollViewDidEndDragging:willDecelerate:方法
也就是说, 只要设置好了UIScrollView的代理对象,那么当某个事件被触发以后,系统会自动调用代理对象的相应方法。我们要关心的就是如何设置代理,其他细节无需关心。
•UIScrollView将delegate需要实现的方法都定义在了UIScrollViewDelegate协议中,因此要想成为UIScrollView的delegate,必须遵守UIScrollViewDelegate协议,然后实现协议中相应的方法,就可以监听UIScrollView的滚动过程了
代理设计模式的作用总结:
•1.监听事件(返回来就是"通知")
–1>scrolView发生某某事件后,通知代理对象的某个方法
–2>代理对象的某个方法监听scrollView的某个事件(状态发生改变)
•2.回传数据
•总结:代理设计模式最终的目的就是”解耦”。
当用户在UIScrollView身上使用捏合手势时,UIScrollView会调用代理的viewForZoomingInScrollView:方法,这个方法返回的控件就是需要进行缩放的控件
注意:UIScrollView 一次只能缩放一个子控件。
实现图片缩放的具体步骤:
•1.添加UIScrollView,设置UIScrollView的宽和高与控制器大小一致
•2.向UIScrollView中添加子控件UIImageView,设置图片,设置UIImageView的大小与图片的实际大小一致。
•3.设置UIScrollView的代理为当前控制器
•4.设置当前控制器遵守UIScrollViewDelegate代理协议
•5.在控制器中实现代理方法
–-(UIView*)viewForZoomingInScrollView:方法返回要缩放的子控件
•6.在viewDidLoad中设置缩放比例
–self.scrollView.maximumZoomScale=2.0;
–self.scrollView.minimumZoomScale=0.4;
•**解释UIScrollViewDelegate中的@optional关键字、@required关键字
Ø即将开始缩放的时候调用
-(void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
Ø正在缩放的时候调用-(void)scrollViewDidZoom:(UIScrollView*)scrollView
Ø缩放完毕的时候调用-(void)scrollViewDidEndZooming::(UIScrollView *)scrollView
图片轮播器:
•实现思路:
–1.添加UIScrollView
–2.动态向UIScrollView中添加图片框(横向)
–3.设置UIScrollView的contentSize实现滚动,实现横向滚动
–4.实现分页
–5.实现分页指示器UIPageControl
–6.通过使用Nstimer实现自动滚动
图片轮播器实现具体步骤
•1.创建一个UIScrollView,设置宽为300,高为130(与每张图片的大小一致)
•2.向UIScrollView中添加内容(要滚动的内容,添加到UIScrollView的子控件集合中)–循环添加5个UIImageView,设置图片,设置frame
•3.设置UIScrollView的contentSize的width为5个图片的总大小,上下不滚动所以height为0
•4.去掉水平滚动条
–self.scrollView.showsHorizontalScrollIndicator= NO;
•5.实现自动分页–self.scrollView.pagingEnabled=YES;
•问题:设置完pagingEnabled=YES以后,scrollView是怎么知道该如何分页的?
–答:按照UIScrollView自身的宽度来实现分页的.UIScrollView的宽度就是每页的大小。
•6.显示分页指示器
–1>通过UIPageControl来实现
–2>拽一个UIPageControl放到控制器的view中,不要放到UIScrollView中,否则就一起滚动了.
–3>设置UIPageControl的TintColor(其他页颜色)和CurrentPage(当前页颜色)属性颜色
•注意:当把UIPageControl添加到控制器的view中的时候,这个控件和UIScrollView根本没有任何联系,所以没有分页指示功能
•7.实现分页指示器总页数、当前页。–总页数:numberOfPages属性
•self.pageControl.numberOfPages=imageCount;–当前页:currentPage属性
•self.pageControl.currentPage= 0;
•注意:
–在viewDidLoad中设置总页数
–在-(void)scrollViewDidScroll:代理方法中设置当前页
–设置当前页的思路:•通过当前的滚动的偏移值来计算出当前滚动到第几页了
•8.通过定时器(NSTimer)实现自动滚动
–在viewDidLoad中启动定时器•启动定时器的两种方法:
•1>调用timerWithXxx创建的timer,把这个timer对象手动加到”消息循环”中才能启动
•2>调用scheduledTimerWithXxx创建的timer,自动启动(创建完毕后自动启动)。
•9.在定时器的方法中实现滚动 –思路1:
–1>通过UIPageControl获取当前页数,并让页数+1
–2>根据加1以后的页数乘以每页的宽度(每张图片宽度)计算出contentOffset.x的偏移值
–3>手动设置偏移值,实现滚动(通过动画方式设置).
•10.解决Bug
–Bug:当拖拽UIScrollView的时候,保持一段时间不松手的时候,一旦松手UIScrollView会连续滚动多次。
–解决思路:在即将拖拽的时候,停止计时器,拖拽完毕后再打开一个计时器。
•**停止计时器:调用NSTimer对象的invalidate方法(当某个计时器被停止以后,就无法再重用了,下次必须再重新创建一个新的计时器)。[self.timerinvalidate];
•-(void)scrollViewWillBeginDragging:
•-(void)scrollViewDidEndDragging:
•11.解决Bug
–Bug:当单击(拖拽)界面上的某个其他控件的时候,UIScrollView停止滚动的问题。
•产生Bug的原因:
–当前处理UI界面的只有一个线程,当这个线程处理UI的拖动事件的时候就没有能力再去处理滚动操作了
–注意:处理UI界面的的只能是一个线程。所以,处理UIScrollView的滚动和其他控件的拖拽,只能用同一个线程。如果多个线程都可以操作UI那么就会造成混乱的问题
•解决思路:提高处理滚动的timer的优先级。
•注意:所有控件的默认优先级都是NSRunLoopCommonModes,但是网络和计时器对象默认的优先级要比控件的优先级低是NSDefaultRunLoopMode,所以这里要把计时器的优先级调整为与控件一样的优先级NSRunLoopCommonModes。
12、分页
•只要将UIScrollView的pageEnabled属性设置为YES,UIScrollView会被分割成多个独立页面,里面的内容就能进行分页展示
•一般会配合UIPageControl增强分页效果,UIPageControl常用属性如下
Ø一共有多少页
@property(nonatomic) NSInteger numberOfPages;
Ø当前显示的页码
@property(nonatomic) NSInteger currentPage;
Ø只有一页时,是否需要隐藏页码指示器
@property(nonatomic) BOOL hidesForSinglePage;
Ø其他页码指示器的颜色
@property(nonatomic,retain) UIColor *pageIndicatorTintColor;
Ø当前页码指示器的颜色
@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;
13.NSTimer
•NSTimer叫做“定时器”,它的作用如下
Ø在指定的时间执行指定的任务
Ø每隔一段时间执行指定的任务
•调用下面的方法就会开启一个定时任务
+(NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)titarget:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInforepeats:(BOOL)yesOrNo;
每隔ti秒,调用一次aTarget的aSelector方法,yesOrNo决定了是否重复执行这个任务
•通过invalidate方法可以停止定时器的工作,一旦定时器被停止了,就不能再次执行任务。只能再创建一个新的定时器才能执行新的任务
-(void)invalidate;