關(guān)于UIStrollview:
UIScrollView無法滾動(dòng)可能的原因及解決辦法:
?沒有設(shè)置contentSize
?scrollEnabled=NO
?沒有接收到觸摸事件:userInteractionEnabled=NO
?沒有取消autolayout功能(要想scrollView滾動(dòng)伤疙,在xcode5.x下必須取消autolayout)注意:在xcode6.1下不需要取消自動(dòng)布局也可以滾動(dòng)旷余。但是從Xcode7開始系統(tǒng)建議我們使用AutoLayout來布局UIScorllView
?UIScrollView的frame.size與contentSize的區(qū)別?
–frame.size指的是:UIScrollView的可視區(qū)域的大小,UIScrollView本身的大小
–contentSize指的是:UIScrollView中所包含的內(nèi)容的大小(要滾動(dòng)的實(shí)際內(nèi)容的大小)
?把frame.size和contentSize設(shè)置都一樣了,還能滾動(dòng)嗎?如果contentSize比frame.size小還能滾動(dòng)嗎?
?總結(jié):在UIScrollView的frame.size這么大的范圍內(nèi),要顯示contentSize這么大的內(nèi)容揍移。是否需要滾動(dòng),取決于contentSize是否比frame.size大乘粒。
?@property(nonatomic)CGPointcontentOffset;幢妄?
?屬性含義:–1>當(dāng)UIScrollView內(nèi)部的內(nèi)容滾動(dòng)時(shí),內(nèi)容相對(duì)于UIScrollView左上角的偏移
? ? ? ? ? ? ? ? ? –2>另一種理解方式:內(nèi)容滾動(dòng)到了什么位置
?通過點(diǎn)擊按鈕,實(shí)現(xiàn)大圖自動(dòng)滾動(dòng)(修改contentOffset)着裹?
?1.直接實(shí)現(xiàn),直接修改contentOffset沒有動(dòng)畫效果
?2.通過UIView的動(dòng)畫方法實(shí)現(xiàn)
?3.通過調(diào)用UIScrollView的setContentOffset:animated:來實(shí)現(xiàn)帶動(dòng)畫效果的滾動(dòng)。
?@property(nonatomic)UIEdgeInsetscontentInset;瑰妄?
?含義:
?內(nèi)容的內(nèi)邊距
?設(shè)置UIScrollView的內(nèi)容在拖動(dòng)以后,內(nèi)容距離UIScrollView的內(nèi)邊距陷嘴。(聯(lián)想按鈕的內(nèi)邊距屬性:Inset)
?另一種思考方式:想象成把內(nèi)容加大了,在內(nèi)容本身的周圍加了一圈”外邊距”。
UIScrollView的其他屬性间坐?
?@property(nonatomic)BOOLbounces;
?設(shè)置UIScrollView是否需要彈簧效果
?@property(nonatomic,getter=isScrollEnabled)BOOLscrollEnabled;
?設(shè)置UIScrollView是否能滾動(dòng)
?@property(nonatomic)BOOLshowsHorizontalScrollIndicator;
?是否顯示水平滾動(dòng)條
?@property(nonatomic)BOOLshowsVerticalScrollIndicator;
?是否顯示垂直滾動(dòng)條
如何做一個(gè)電臺(tái)參考步驟灾挨?
?1>拖拽一個(gè)UIScrollView到控制器view,設(shè)置該UIScrollView大小與控制器view一致
?2>設(shè)置該UIScrollView的背景色為RGB:212,212,212
?3>向UIScrollView中增加內(nèi)容
?4>設(shè)置UIScrollView的contentSize的height為最下面的圖片的最大的Y值,width為0(因?yàn)闄M向不滾動(dòng))
?提示:某個(gè)方向上不希望滾動(dòng),則把該方向上的contentSize的值設(shè)置為0
?5>向控制器的view中添加一個(gè)UIView到最上方,模擬"導(dǎo)航欄”
?注意:直接拖拽UIView到UIScrollView上,就導(dǎo)致UIView隨著UIScrollView進(jìn)行滾動(dòng),
這個(gè)UIView不屬于UIScrollView所以拖拽的時(shí)候最好拖拽到Scene(場(chǎng)景)上。在viewDidLoad中設(shè)置contentOffset的y值,為-64(設(shè)置默認(rèn)滾動(dòng)的位置).
?6>在最底部拖拽一個(gè)UIView,模擬”底部菜單”,高度為44
?7>設(shè)置頂部"導(dǎo)航欄UIView"與 底部"菜單欄UIView"的alpha= 0.7(設(shè)置透明度)
?8>設(shè)置contentInset屬性的top和bottom的值,在滾動(dòng)后預(yù)留一定的內(nèi)邊距
?注意:獲取某個(gè)控件的最大的Y值:CGRectGetMaxY(self.lastButton.frame);
?9>設(shè)置一開始就滾動(dòng)到某個(gè)位置,通過contentOffset屬性實(shí)現(xiàn)
?注意這里要把y值設(shè)置為負(fù)數(shù)
實(shí)現(xiàn)滾動(dòng)的時(shí)候輸出當(dāng)前滾動(dòng)的位置眶诈?
思考:
1.獲取當(dāng)前滾動(dòng)的位置:scrollView.contentOffset
2.要想實(shí)現(xiàn)滾動(dòng)的時(shí)候顯示當(dāng)前滾動(dòng)的位置,那么就一定要監(jiān)聽滾動(dòng)事件涨醋。
3.問題:如何監(jiān)聽滾動(dòng)事件?答:通過代理來監(jiān)聽逝撬。
監(jiān)聽事件的另外一種方式:代理浴骂。之前學(xué)過的一種方式是:addTarget的方式。
用戶開始拖拽時(shí)宪潮,調(diào)用scrollViewWillBeginDragging:方法
具體滾動(dòng)到某個(gè)位置時(shí)溯警,調(diào)用scrollViewDidScroll:方法
用戶停止拖拽時(shí),調(diào)用scrollViewDidEndDragging:willDecelerate:方法
也就是說, 只要設(shè)置好了UIScrollView的代理對(duì)象,那么當(dāng)某個(gè)事件被觸發(fā)以后,系統(tǒng)會(huì)自動(dòng)調(diào)用代理對(duì)象的相應(yīng)方法狡相。我們要關(guān)心的就是如何設(shè)置代理,其他細(xì)節(jié)無需關(guān)心梯轻。
?UIScrollView將delegate需要實(shí)現(xiàn)的方法都定義在了UIScrollViewDelegate協(xié)議中,因此要想成為UIScrollView的delegate尽棕,必須遵守UIScrollViewDelegate協(xié)議喳挑,然后實(shí)現(xiàn)協(xié)議中相應(yīng)的方法,就可以監(jiān)聽UIScrollView的滾動(dòng)過程了
代理設(shè)計(jì)模式的作用總結(jié):
?1.監(jiān)聽事件(返回來就是"通知")
–1>scrolView發(fā)生某某事件后,通知代理對(duì)象的某個(gè)方法
–2>代理對(duì)象的某個(gè)方法監(jiān)聽scrollView的某個(gè)事件(狀態(tài)發(fā)生改變)
?2.回傳數(shù)據(jù)
?總結(jié):代理設(shè)計(jì)模式最終的目的就是”解耦”伊诵。
當(dāng)用戶在UIScrollView身上使用捏合手勢(shì)時(shí)单绑,UIScrollView會(huì)調(diào)用代理的viewForZoomingInScrollView:方法,這個(gè)方法返回的控件就是需要進(jìn)行縮放的控件
注意:UIScrollView 一次只能縮放一個(gè)子控件曹宴。
實(shí)現(xiàn)圖片縮放的具體步驟:
?1.添加UIScrollView,設(shè)置UIScrollView的寬和高與控制器大小一致
?2.向UIScrollView中添加子控件UIImageView,設(shè)置圖片,設(shè)置UIImageView的大小與圖片的實(shí)際大小一致搂橙。
?3.設(shè)置UIScrollView的代理為當(dāng)前控制器
?4.設(shè)置當(dāng)前控制器遵守UIScrollViewDelegate代理協(xié)議
?5.在控制器中實(shí)現(xiàn)代理方法
–-(UIView*)viewForZoomingInScrollView:方法返回要縮放的子控件
?6.在viewDidLoad中設(shè)置縮放比例
–self.scrollView.maximumZoomScale=2.0;
–self.scrollView.minimumZoomScale=0.4;
?**解釋UIScrollViewDelegate中的@optional關(guān)鍵字、@required關(guān)鍵字
?即將開始縮放的時(shí)候調(diào)用
-(void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
?正在縮放的時(shí)候調(diào)用-(void)scrollViewDidZoom:(UIScrollView*)scrollView
?縮放完畢的時(shí)候調(diào)用-(void)scrollViewDidEndZooming::(UIScrollView *)scrollView
圖片輪播器:
?實(shí)現(xiàn)思路:
–1.添加UIScrollView
–2.動(dòng)態(tài)向UIScrollView中添加圖片框(橫向)
–3.設(shè)置UIScrollView的contentSize實(shí)現(xiàn)滾動(dòng),實(shí)現(xiàn)橫向滾動(dòng)
–4.實(shí)現(xiàn)分頁
–5.實(shí)現(xiàn)分頁指示器UIPageControl
–6.通過使用Nstimer實(shí)現(xiàn)自動(dòng)滾動(dòng)
圖片輪播器實(shí)現(xiàn)具體步驟
?1.創(chuàng)建一個(gè)UIScrollView,設(shè)置寬為300,高為130(與每張圖片的大小一致)
?2.向UIScrollView中添加內(nèi)容(要滾動(dòng)的內(nèi)容,添加到UIScrollView的子控件集合中)–循環(huán)添加5個(gè)UIImageView,設(shè)置圖片,設(shè)置frame
?3.設(shè)置UIScrollView的contentSize的width為5個(gè)圖片的總大小,上下不滾動(dòng)所以height為0
?4.去掉水平滾動(dòng)條
–self.scrollView.showsHorizontalScrollIndicator= NO;
?5.實(shí)現(xiàn)自動(dòng)分頁–self.scrollView.pagingEnabled=YES;
?問題:設(shè)置完pagingEnabled=YES以后笛坦,scrollView是怎么知道該如何分頁的?
–答:按照UIScrollView自身的寬度來實(shí)現(xiàn)分頁的.UIScrollView的寬度就是每頁的大小区转。
?6.顯示分頁指示器
–1>通過UIPageControl來實(shí)現(xiàn)
–2>拽一個(gè)UIPageControl放到控制器的view中,不要放到UIScrollView中,否則就一起滾動(dòng)了.
–3>設(shè)置UIPageControl的TintColor(其他頁顏色)和CurrentPage(當(dāng)前頁顏色)屬性顏色
?注意:當(dāng)把UIPageControl添加到控制器的view中的時(shí)候,這個(gè)控件和UIScrollView根本沒有任何聯(lián)系,所以沒有分頁指示功能
?7.實(shí)現(xiàn)分頁指示器總頁數(shù)、當(dāng)前頁版扩。–總頁數(shù):numberOfPages屬性
?self.pageControl.numberOfPages=imageCount;–當(dāng)前頁:currentPage屬性
?self.pageControl.currentPage= 0;
?注意:
–在viewDidLoad中設(shè)置總頁數(shù)
–在-(void)scrollViewDidScroll:代理方法中設(shè)置當(dāng)前頁
–設(shè)置當(dāng)前頁的思路:?通過當(dāng)前的滾動(dòng)的偏移值來計(jì)算出當(dāng)前滾動(dòng)到第幾頁了
?8.通過定時(shí)器(NSTimer)實(shí)現(xiàn)自動(dòng)滾動(dòng)
–在viewDidLoad中啟動(dòng)定時(shí)器?啟動(dòng)定時(shí)器的兩種方法:
?1>調(diào)用timerWithXxx創(chuàng)建的timer废离,把這個(gè)timer對(duì)象手動(dòng)加到”消息循環(huán)”中才能啟動(dòng)
?2>調(diào)用scheduledTimerWithXxx創(chuàng)建的timer,自動(dòng)啟動(dòng)(創(chuàng)建完畢后自動(dòng)啟動(dòng))资厉。
?9.在定時(shí)器的方法中實(shí)現(xiàn)滾動(dòng) ? –思路1:
–1>通過UIPageControl獲取當(dāng)前頁數(shù),并讓頁數(shù)+1
–2>根據(jù)加1以后的頁數(shù)乘以每頁的寬度(每張圖片寬度)計(jì)算出contentOffset.x的偏移值
–3>手動(dòng)設(shè)置偏移值,實(shí)現(xiàn)滾動(dòng)(通過動(dòng)畫方式設(shè)置).
?10.解決Bug
–Bug:當(dāng)拖拽UIScrollView的時(shí)候,保持一段時(shí)間不松手的時(shí)候,一旦松手UIScrollView會(huì)連續(xù)滾動(dòng)多次厅缺。
–解決思路:在即將拖拽的時(shí)候,停止計(jì)時(shí)器,拖拽完畢后再打開一個(gè)計(jì)時(shí)器蔬顾。
?**停止計(jì)時(shí)器:調(diào)用NSTimer對(duì)象的invalidate方法(當(dāng)某個(gè)計(jì)時(shí)器被停止以后,就無法再重用了,下次必須再重新創(chuàng)建一個(gè)新的計(jì)時(shí)器)宴偿。[self.timerinvalidate];
?-(void)scrollViewWillBeginDragging:
?-(void)scrollViewDidEndDragging:
?11.解決Bug
–Bug:當(dāng)單擊(拖拽)界面上的某個(gè)其他控件的時(shí)候,UIScrollView停止?jié)L動(dòng)的問題。
?產(chǎn)生Bug的原因:
–當(dāng)前處理UI界面的只有一個(gè)線程,當(dāng)這個(gè)線程處理UI的拖動(dòng)事件的時(shí)候就沒有能力再去處理滾動(dòng)操作了
–注意:處理UI界面的的只能是一個(gè)線程诀豁。所以,處理UIScrollView的滾動(dòng)和其他控件的拖拽,只能用同一個(gè)線程窄刘。如果多個(gè)線程都可以操作UI那么就會(huì)造成混亂的問題
?解決思路:提高處理滾動(dòng)的timer的優(yōu)先級(jí)。
?注意:所有控件的默認(rèn)優(yōu)先級(jí)都是NSRunLoopCommonModes,但是網(wǎng)絡(luò)和計(jì)時(shí)器對(duì)象默認(rèn)的優(yōu)先級(jí)要比控件的優(yōu)先級(jí)低是NSDefaultRunLoopMode,所以這里要把計(jì)時(shí)器的優(yōu)先級(jí)調(diào)整為與控件一樣的優(yōu)先級(jí)NSRunLoopCommonModes舷胜。
12娩践、分頁
?只要將UIScrollView的pageEnabled屬性設(shè)置為YES,UIScrollView會(huì)被分割成多個(gè)獨(dú)立頁面烹骨,里面的內(nèi)容就能進(jìn)行分頁展示
?一般會(huì)配合UIPageControl增強(qiáng)分頁效果翻伺,UIPageControl常用屬性如下
?一共有多少頁
@property(nonatomic) NSInteger numberOfPages;
?當(dāng)前顯示的頁碼
@property(nonatomic) NSInteger currentPage;
?只有一頁時(shí),是否需要隱藏頁碼指示器
@property(nonatomic) BOOL hidesForSinglePage;
?其他頁碼指示器的顏色
@property(nonatomic,retain) UIColor *pageIndicatorTintColor;
?當(dāng)前頁碼指示器的顏色
@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;
13.NSTimer
?NSTimer叫做“定時(shí)器”沮焕,它的作用如下
?在指定的時(shí)間執(zhí)行指定的任務(wù)
?每隔一段時(shí)間執(zhí)行指定的任務(wù)
?調(diào)用下面的方法就會(huì)開啟一個(gè)定時(shí)任務(wù)
+(NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)titarget:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInforepeats:(BOOL)yesOrNo;
每隔ti秒吨岭,調(diào)用一次aTarget的aSelector方法,yesOrNo決定了是否重復(fù)執(zhí)行這個(gè)任務(wù)
?通過invalidate方法可以停止定時(shí)器的工作峦树,一旦定時(shí)器被停止了辣辫,就不能再次執(zhí)行任務(wù)。只能再創(chuàng)建一個(gè)新的定時(shí)器才能執(zhí)行新的任務(wù)
-(void)invalidate;