UIScrollView
前言:UIScrollView使用非常廣,本文研究UIScrollView各屬性和方法,明白它們的意義、作用。在后面的一篇文章有整理UIScrollView一些常見用法以及一些效果的實現思路。 --參考文章: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用于在一個小范圍里顯示很大的內容的控件。通過用戶平滑、手捏手勢,在這個小區域里查看不同內容。是UITableView和UITextView的父類。它是視圖,但是比較特殊,可以看成把它看成2層的結構。上面是它的frame層,跟一般試圖一樣,是它的可見區域,下面層是contentView,可以滑動。? ======常用屬性====== -- CGPoint contentOffSet :contentView的偏移值(正常contentOffSet.x/y值都為正數,但有時(bounces = YES)拽出邊界了或者 contentInset 設置了,還是會出現負數,伴隨著contentView滑動,總在改變);--CGSize contentSize :contentView的大小;--UIEdgeInsets contentInset :contentView四周的擴展大小,相當改變ContentView的大小,但不是改變contentSize(UIEdgeInsets是個結構體,里面的數值可能是負數,所以擴展的結果可能是contentView被蠶食了一部分。但不管contentView變大了還是變小了,contentOffSet的值還是相比原來大小的偏移);--iddelegate :它的代理;
--BOOL directionalLockEnabled :默認是NO,可以在垂直和水平方向同時運動。當值是YES時,假如一開始是垂直或者是水平運動,那么接下來會鎖定另外一個方向的滾動。假如一開始是對角方向滾動,則不會禁止某個方向(測試鎖定不了,難道是contentsize跟frame高度或寬度一樣時用的)
- -BOOL bounces :默認是 yes,就是滾動超過邊界會反彈有反彈回來的效果。假如是 NO,那么滾動到達邊界會立刻停止
--UIScrollViewIndicatorStyle? indicatorStyle :設定滾動條的樣式;
--BOOL alwaysBounceVertical: 默認no,控制垂直方向遇到邊框是否反彈(但bounces為NO時,它為yes,也不反彈。/if YES and bounces is YES, even if content is smaller than bounds, allow drag vertically,測試不好使);
--BOOL alwaysBounceHorizontal: 默認no,控制水平方向遇到邊框是否反彈(但bounces為NO時,它為yes,也不反彈);
--BOOL pagingEnabled: default NO,contentView是否整頁翻動;
--BOOL scrollEnabled :default YES,contentView是否能滾動;
--BOOL showsHorizontalScrollIndicator :default YES,是否顯示水平方向的滾動條;
--BOOL showsVerticalScrollIndicator :default YES? 是否顯示垂直方向的滾動條;
--UIEdgeInsets scrollIndicatorInsets :滾動條在scrollerView中的位置的擴展;
--float? decelerationRate :手指放開后的減速率(測試發現設定這個值沒用);
============交互相關============
--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的事件響應順序跟一般的不同,一般的見參考文檔, UIScrollView 的工作原理,當手指 touch 的時候, UIScrollView 會攔截 Event, 會等待一段時間,在這段時間內,如果沒有手指沒有移動,當時間結束時, UIScrollView 會發送 tracking events 到子視圖上。在時間結束前,手指發生了移動,那么 UIScrollView 就會進行移動,從而取笑發送 tracking 順序說明: 當手指 touch 的時候,如果 scrollView 上面有可交互的視圖, track, ->或滑動或點擊
--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 時,松開了即為 no 了
--BOOL decelerating : (readonly) returns YES if user isn't dragging (touch up) but scroll view is still moving
--BOOL delaysContentTouches :就是手指點擊到類的時候,如果它為 yes ,則按之前講的處理,如果為 no ,并且點在了 “ 可交互的視圖 ” ,立馬調用 touchesShouldBegin
-- BOOL? canCancelContentTouches: 是 if touches have already been delivered to a subview of the scroll view 之后發生的事,如果 no ,即使 touch move ,也不 scroll 了,反之 如果是 yes , tracking 后,手指移動,會調用 touchesShouldCancelInContentView 方法;
-- 備注:注意順序,所以當 delaysContentTouches 為 no , canCancelContentTouches 為 no 的時候, touchesShouldBegin 方法的返回值不同,滑動在 “ 可交互的視圖 ” 的效果也不同,一個滑的動,一個滑不動 ( 注意是 touch move 了之后的事情 )
------------ 相關方法 ------------
// 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
-- 調用地方:方法在 UIScrollView 的子類中被重寫,被調用,
--調用時候:如果delaysContentTouches為yes,則手指點擊的時候,會捕獲到Event,等待一段時間,在這段時間內,如果沒有手指沒有移動,并且手指點擊在了一個“可交互的視圖”則調用touchesShouldBegin,否則類scroll。如果delaysContentTouches為no,只要手指點擊了,并且點在一個“可交互的視圖”,立刻調用touchesShouldBegin方法。
--備注:當點擊子類中的“可交互的視圖”上時,如果返回值為no,點擊事件不會傳遞給子視圖了。( 例如上面加了一個 button ,如果它返回 no ,點擊 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;
-- 調用時候,上面已講, -- 返回值說明: yes ,發生滾動, touch 不在傳遞給子視圖, no ,不滾動, touch 傳遞給子視圖
總結: 用戶 touch --》 tracking 真--》 如果點擊一個可交互視圖上,發生后面的事,如果沒有,一般情況--》
步驟 1 :根據 delaysContentTouches 的值,判斷什么時候 步驟 2 (立刻還是判斷一定條件);
步驟 2 :調用 touchesShouldBegin 方法,如果返回值為 yes , touch 事件傳給子視圖;如果為 no , touch 事件不傳給子視圖,進入狀態 n 。(跳轉)
步驟 3 : touch move 的,如果 canCancelContentTouches 為 no ,不調用 touchesShouldCancelInContentView 方法,類也不 scroll ,進入狀態 m ,如果 canCancelContentTouches 為 yes ,調用 touchesShouldCancelInContentView ,根據 touchesShouldCancelInContentView 方法的返回值,如果是 yes, 進入狀態 m 。如果是 no, 進入狀態 s 。
狀態 n : tracking 為真,如果 touch move 的就 scroll , touch 松開,進入狀態 e
狀態 s : touch move 中,類 scroll , 如果 touch 松開,進入狀態 e
狀態 m : touch move 中,類不 scroll , 如果 touch 松開,進入狀態 e
狀態 e :結束
============ 縮放相關 ============
--float minimumZoomScale : 縮放的最小比例;
--float maximumZoomScale :縮放的最大比例;
-- float zoomScale : 縮放的比例 ( 在 minimumZoomScale 和 maximumZoomScale 之間變化 ); 如果設置的話,寫在 [self.view addSubview:_scrollView]; 之后才能好使
--BOOL bouncesZoom : 控制縮放到邊界的時是否會反彈 ;
--BOOL zooming(readonly) :判斷控件的大小是否正在縮放 ;
--BOOL zoomBouncing(readonly) :判斷控件是否 縮放到了最大/最小 ;
-- 備注:如果 scollView 設置了縮放,但又設置 contentszie 等,剛開始沒縮放的時候能 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.
設置單擊狀態欄控件是否滾動到頂部
--BOOL scrollsToTop :