UIScrollView
前言:UIScrollView使用非常廣,本文研究UIScrollView各屬性和方法,明白它們的意義、作用。在后面的一篇文章有整理UIScrollView一些常見用法以及一些效果的實(shí)現(xiàn)思路。 --參考文章:http://www.cocoachina.com/iphonedev/sdk/2010/1224/2503.html? &&? http://zjqzy03080312.blog.163.com/blog/static/18574280720121121105928687? &&? http://blog.csdn.net/wzzvictory/article/details/9264335? --官方查閱文檔? https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html? --介紹:UIScrollView用于在一個(gè)小范圍里顯示很大的內(nèi)容的控件。通過用戶平滑、手捏手勢(shì),在這個(gè)小區(qū)域里查看不同內(nèi)容。是UITableView和UITextView的父類。它是視圖,但是比較特殊,可以看成把它看成2層的結(jié)構(gòu)。上面是它的frame層,跟一般試圖一樣,是它的可見區(qū)域,下面層是contentView,可以滑動(dòng)。? ======常用屬性====== -- CGPoint contentOffSet :contentView的偏移值(正常contentOffSet.x/y值都為正數(shù),但有時(shí)(bounces = YES)拽出邊界了或者 contentInset 設(shè)置了,還是會(huì)出現(xiàn)負(fù)數(shù),伴隨著contentView滑動(dòng),總在改變);--CGSize contentSize :contentView的大??;--UIEdgeInsets contentInset :contentView四周的擴(kuò)展大小,相當(dāng)改變ContentView的大小,但不是改變contentSize(UIEdgeInsets是個(gè)結(jié)構(gòu)體,里面的數(shù)值可能是負(fù)數(shù),所以擴(kuò)展的結(jié)果可能是contentView被蠶食了一部分。但不管contentView變大了還是變小了,contentOffSet的值還是相比原來大小的偏移);--iddelegate :它的代理;
--BOOL directionalLockEnabled :默認(rèn)是NO,可以在垂直和水平方向同時(shí)運(yùn)動(dòng)。當(dāng)值是YES時(shí),假如一開始是垂直或者是水平運(yùn)動(dòng),那么接下來會(huì)鎖定另外一個(gè)方向的滾動(dòng)。假如一開始是對(duì)角方向滾動(dòng),則不會(huì)禁止某個(gè)方向(測(cè)試鎖定不了,難道是contentsize跟frame高度或?qū)挾纫粯訒r(shí)用的)
- -BOOL bounces :默認(rèn)是 yes,就是滾動(dòng)超過邊界會(huì)反彈有反彈回來的效果。假如是 NO,那么滾動(dòng)到達(dá)邊界會(huì)立刻停止
--UIScrollViewIndicatorStyle? indicatorStyle :設(shè)定滾動(dòng)條的樣式;
--BOOL alwaysBounceVertical: 默認(rèn)no,控制垂直方向遇到邊框是否反彈(但bounces為NO時(shí),它為yes,也不反彈。/if YES and bounces is YES, even if content is smaller than bounds, allow drag vertically,測(cè)試不好使);
--BOOL alwaysBounceHorizontal: 默認(rèn)no,控制水平方向遇到邊框是否反彈(但bounces為NO時(shí),它為yes,也不反彈);
--BOOL pagingEnabled: default NO,contentView是否整頁(yè)翻動(dòng);
--BOOL scrollEnabled :default YES,contentView是否能滾動(dòng);
--BOOL showsHorizontalScrollIndicator :default YES,是否顯示水平方向的滾動(dòng)條;
--BOOL showsVerticalScrollIndicator :default YES? 是否顯示垂直方向的滾動(dòng)條;
--UIEdgeInsets scrollIndicatorInsets :滾動(dòng)條在scrollerView中的位置的擴(kuò)展;
--float? decelerationRate :手指放開后的減速率(測(cè)試發(fā)現(xiàn)設(shè)定這個(gè)值沒用);
============交互相關(guān)============
--Scrolling with no scroll bars is a bit complex. on touch down, we don't know if the user will want to scroll or track a subview like a control.
on touch down, we start a timer and also look at any movement. if the time elapses without sufficient change in position, we start sending events to? the hit view in the content subview. if the user then drags far enough, we switch back to dragging and cancel any tracking in the subview.
the methods below are called by the scroll view and give subclasses override points to add in custom behavior.
you can remove the delay in delivery of touchesBegan:withEvent: to subviews by setting delaysContentTouches to NO.
--UIScrollView的事件響應(yīng)順序跟一般的不同,一般的見參考文檔, UIScrollView 的工作原理,當(dāng)手指 touch 的時(shí)候, UIScrollView 會(huì)攔截 Event, 會(huì)等待一段時(shí)間,在這段時(shí)間內(nèi),如果沒有手指沒有移動(dòng),當(dāng)時(shí)間結(jié)束時(shí), UIScrollView 會(huì)發(fā)送 tracking events 到子視圖上。在時(shí)間結(jié)束前,手指發(fā)生了移動(dòng),那么 UIScrollView 就會(huì)進(jìn)行移動(dòng),從而取笑發(fā)送 tracking 順序說明: 當(dāng)手指 touch 的時(shí)候,如果 scrollView 上面有可交互的視圖, track, ->或滑動(dòng)或點(diǎn)擊
--BOOL tracking : (readonly)returns YES if user has touched. may not yet have started dragging, 即用戶按上了,不管滑沒滑
--BOOL dragging : (readonly)returns YES if user has started scrolling. this may require some time and or distance to move to initiate dragging, 用戶在手指在 scrolll 時(shí),松開了即為 no 了
--BOOL decelerating : (readonly) returns YES if user isn't dragging (touch up) but scroll view is still moving
--BOOL delaysContentTouches :就是手指點(diǎn)擊到類的時(shí)候,如果它為 yes ,則按之前講的處理,如果為 no ,并且點(diǎn)在了 “ 可交互的視圖 ” ,立馬調(diào)用 touchesShouldBegin
-- BOOL? canCancelContentTouches: 是 if touches have already been delivered to a subview of the scroll view 之后發(fā)生的事,如果 no ,即使 touch move ,也不 scroll 了,反之 如果是 yes , tracking 后,手指移動(dòng),會(huì)調(diào)用 touchesShouldCancelInContentView 方法;
-- 備注:注意順序,所以當(dāng) delaysContentTouches 為 no , canCancelContentTouches 為 no 的時(shí)候, touchesShouldBegin 方法的返回值不同,滑動(dòng)在 “ 可交互的視圖 ” 的效果也不同,一個(gè)滑的動(dòng),一個(gè)滑不動(dòng) ( 注意是 touch move 了之后的事情 )
------------ 相關(guān)方法 ------------
// override points for subclasses to control delivery of touch events to subviews of the scroll view
// called before touches are delivered to a subview of the scroll view. if it returns NO the touches will not be delivered to the subview
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view; // default returns YES
-- 調(diào)用地方:方法在 UIScrollView 的子類中被重寫,被調(diào)用,
--調(diào)用時(shí)候:如果delaysContentTouches為yes,則手指點(diǎn)擊的時(shí)候,會(huì)捕獲到Event,等待一段時(shí)間,在這段時(shí)間內(nèi),如果沒有手指沒有移動(dòng),并且手指點(diǎn)擊在了一個(gè)“可交互的視圖”則調(diào)用touchesShouldBegin,否則類scroll。如果delaysContentTouches為no,只要手指點(diǎn)擊了,并且點(diǎn)在一個(gè)“可交互的視圖”,立刻調(diào)用touchesShouldBegin方法。
--備注:當(dāng)點(diǎn)擊子類中的“可交互的視圖”上時(shí),如果返回值為no,點(diǎn)擊事件不會(huì)傳遞給子視圖了。( 例如上面加了一個(gè) button ,如果它返回 no ,點(diǎn)擊 button ,沒有效果 ) 。 yes 反之 ;
// called before scrolling begins if touches have already been delivered to a subview of the scroll view. if it returns NO the touches will continue to be delivered to the subview and scrolling will not occur
// not called if canCancelContentTouches is NO. default returns YES if view isn't a UIControl
- (BOOL)touchesShouldCancelInContentView:(UIView *)view;
-- 調(diào)用時(shí)候,上面已講, -- 返回值說明: yes ,發(fā)生滾動(dòng), touch 不在傳遞給子視圖, no ,不滾動(dòng), touch 傳遞給子視圖
總結(jié): 用戶 touch --》 tracking 真--》 如果點(diǎn)擊一個(gè)可交互視圖上,發(fā)生后面的事,如果沒有,一般情況--》
步驟 1 :根據(jù) delaysContentTouches 的值,判斷什么時(shí)候 步驟 2 (立刻還是判斷一定條件);
步驟 2 :調(diào)用 touchesShouldBegin 方法,如果返回值為 yes , touch 事件傳給子視圖;如果為 no , touch 事件不傳給子視圖,進(jìn)入狀態(tài) n 。(跳轉(zhuǎn))
步驟 3 : touch move 的,如果 canCancelContentTouches 為 no ,不調(diào)用 touchesShouldCancelInContentView 方法,類也不 scroll ,進(jìn)入狀態(tài) m ,如果 canCancelContentTouches 為 yes ,調(diào)用 touchesShouldCancelInContentView ,根據(jù) touchesShouldCancelInContentView 方法的返回值,如果是 yes, 進(jìn)入狀態(tài) m 。如果是 no, 進(jìn)入狀態(tài) s 。
狀態(tài) n : tracking 為真,如果 touch move 的就 scroll , touch 松開,進(jìn)入狀態(tài) e
狀態(tài) s : touch move 中,類 scroll , 如果 touch 松開,進(jìn)入狀態(tài) e
狀態(tài) m : touch move 中,類不 scroll , 如果 touch 松開,進(jìn)入狀態(tài) e
狀態(tài) e :結(jié)束
============ 縮放相關(guān) ============
--float minimumZoomScale : 縮放的最小比例;
--float maximumZoomScale :縮放的最大比例;
-- float zoomScale : 縮放的比例 ( 在 minimumZoomScale 和 maximumZoomScale 之間變化 ); 如果設(shè)置的話,寫在 [self.view addSubview:_scrollView]; 之后才能好使
--BOOL bouncesZoom : 控制縮放到邊界的時(shí)是否會(huì)反彈 ;
--BOOL zooming(readonly) :判斷控件的大小是否正在縮放 ;
--BOOL zoomBouncing(readonly) :判斷控件是否 縮放到了最大/最小 ;
-- 備注:如果 scollView 設(shè)置了縮放,但又設(shè)置 contentszie 等,剛開始沒縮放的時(shí)候能 scroll ,但一但縮放過,就只能縮放,不能 scroll 了
// When the user taps the status bar, the scroll view beneath the touch which is closest to the status bar will be scrolled to top, but only if its `scrollsToTop` property is YES, its delegate does not return NO from `shouldScrollViewScrollToTop`, and it is not already at the top.
// On iPhone, we execute this gesture only if there's one on-screen scroll view with `scrollsToTop` == YES. If more than one is found, none will be scrolled.
設(shè)置單擊狀態(tài)欄控件是否滾動(dòng)到頂部
--BOOL scrollsToTop :