--前言:UIScrollView使用很是廣,本文研究UIScrollView各屬性和方法,明白它們的意義、做用。在後面的一篇文章有整理UIScrollView一些常見用法以及一些效果的實現思路。
html
--參考文章: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
ios
--介紹:UIScrollView用於在一個小範圍裏顯示很大的內容的控件。經過用戶平滑、手捏手勢,在這個小區域裏查看不一樣內容。是UITableView和UITextView的父類。它是視圖,可是比較特殊,能夠當作把它當作2層的結構。上面是它的frame層,跟通常試圖同樣,是它的可見區域,下面層是contentView,能夠滑動。
app
======經常使用屬性======
iphone
--CGPoint contentOffSet:contentView的偏移值(正常contentOffSet.x/y值都爲正數,但有時(bounces = YES)拽出邊界了或者contentInset設置了,仍是會出現負數,伴隨着contentView滑動,總在改變);ide
--CGSize contentSize:contentView的大小;測試
--UIEdgeInsets contentInset:contentView四周的擴展大小,至關改變ContentView的大小,但不是改變contentSize(UIEdgeInsets是個結構體,裏面的數值多是負數,因此擴展的結果多是contentView被蠶食了一部分。但無論contentView變大了仍是變小了,contentOffSet的值仍是相比原來大小的偏移);ui
--id<UIScrollerViewDelegate> delegate:它的代理;this
--BOOL directionalLockEnabled:默認是NO,能夠在垂直和水平方向同時運動。當值是YES時,假如一開始是垂直或者是水平運動,那麼接下來會鎖定另一個方向的滾動。假如一開始是對角方向滾動,則不會禁止某個方向(測試鎖定不了,難道是contentsize跟frame高度或寬度同樣時用的)spa
--BOOL bounces:默認是 yes,就是滾動超過邊界會反彈有反彈回來的效果。假如是 NO,那麼滾動到達邊界會馬上中止.net
--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: