UIScrollView 原理詳解

征途LN發表於2013-12-28


由於專案中用到這個控制元件,本想詳細的做一下作結,發現網上有很詳細的介紹,先轉載學習吧,如果以後發現新內容,自己在重寫一篇
文章出處:http://blog.csdn.net/ch_soft/article/details/6947695

ScrollView

       UIScrollView

     UIScrollView為了顯示多於一個螢幕的內容或者超過你能放在記憶體中的內容。

                 Scroll View為你處理縮小放大手勢,UIScrollView實現了這些手勢,並且替你處理對於它們的探測和迴應。其中需要注意的子類是UITableView以及UITextView(用來顯示大量的文字)。還有一個UIWebView,儘管那不是UIScrollView的直接子類,它適用UIScrollView去顯示網頁內容

        contentsize是內容的寬和高,contentsize.width是內容的寬度,contentsize.heght是高度,contentsizeUIScrollView的一個屬性,它是一個CGSize,是由核心圖形所定義的架構,那定義了你可以滾軸內容的寬度和高度,你也可以新增可以上下滾動的額外區域。第一種方法是你可以通過新增內容的大小來完成。另外一個比較動態的選擇是UIScrollView的另一個屬性contentInsetcontentInset增加你在contentsize中指定的內容能夠滾動的上下左右區域數量contentInset.top以及contentInset.buttom分別表示上面和下面的距離。

           在滾軸檢視中,有一個叫做ContentOffset的屬性跟蹤UIScrollView的具體位置,你能夠自己獲取和設定它,ContentOffset是你當前可視內容在滾軸檢視邊界的左上角那個點。如圖:


           可以看出,ContentOffset內容中的那個點不是從contentInset的左上角開始的,而是內容的左上角,此時的ContentOffset是正值,但有時也是負值,如下圖所示:


使用一個ScrollView

     建立一個UIScrollView

             CGRectframe = CGRectMake( 0, 0, 200, 200);

              scrollView= [[UIScrollView alloc] initWithFrame: frame];

    新增子檢視(框架可以超過scroll view的邊界)

            frame= CGRectMake( 0, 0, 500, 500);

            myImageView= [[UIImageView alloc] initWithFrame: frame];

           [scrollViewaddSubview:myImageView];

    設定內容尺寸

           scrollView.contentSize= CGSize(500,500);


擴充套件Scroll View 的行為

      應用程式通常需要知道有關的滾圖的事件

            scrolloffset改變的時候

           拖動開始和結束

            減速的開始和結束


通過子類化擴充套件Scroll View 的行為

        建立一個子類

        重寫一些功能並改變行為

        關於這種方式的爭議

               應用程式的邏輯和行為變成了檢視本身的一部分,就像,你可能有一些定製的滾軸邏輯,,在那你只在意一個檢視控制,但你想在不同地方重複使用你的滾軸檢視,如果你必須為每個都子類化,你最後會有很多不同的滾軸檢視子類以及在檢視中的特定應用邏輯。

              編寫很多子類是很沉悶的事情,你最後會有很多無法重複使用的單獨檢視,而MVC的檢視部分的一個重點是檢視是可以在不同的控制器和不同的模式之中重複使用的,如果我們把所有邏輯都放在檢視中,它減少了可複用性。

              你的程式碼變得很牢固地配對在一起,它實際上變成了超類的一部分,你無法從UIScrollView中析取它,之後用其它東西代替,如果它在你控制器中且為控制器的一部分,在之後更容易改變它工作的方式和重新安排你應用程式的一些部分。


通過委派來擴充套件Scroll View 的行為(常用的)

         委派是一個單獨的物件,協議,定義了委派會實現的一系列功能的Objective-C協議,它建立了一系列很清晰的撤銷點,在那裡你能定製行為和外觀。它在這些物件之間保持了鬆散的配對,檢視本身與檢視控制器或任何其它的控制器物件,委派不是滾軸檢視的直接子類,它比起牢固配對的子類更加的鬆散。




首先引用別人分析一篇不錯的文章,同時也感謝這位朋友的分享:http://www.cocoachina.com/iphonedev/sdk/2010/1224/2503.html   

  在滾動過程當中,其實是在修改原點座標。當手指觸控後, scroll view會暫時攔截觸控事件,使用一個計時器。假如在計時器到點後沒有發生手指移動事件,那麼 scroll view 傳送 tracking events 到被點選的 subview。假如在計時器到點前發生了移動事件,那麼 scroll view 取消 tracking 自己發生滾動。

    子類可以過載

touchesShouldBegin:withEvent:inContentView: 決定自己是否接收 touch 事件
pagingEnabled:當值是 YES 會自動滾動到 subview 的邊界,預設是NO
touchesShouldCancelInContentView: 開始傳送 tracking messages 訊息給 subview 的時候呼叫這個方法,決定是否傳送 tracking messages 訊息到subview。假如返回 NO,傳送。YES 則不傳送。
假如 canCancelContentTouches屬性是NO,則不呼叫這個方法來影響如何處理滾動手勢。

    scroll view 還處理縮放和平移手勢,要實現縮放和平移,必須實現委託 viewForZoomingInScrollView:、scrollViewDidEndZooming:withView:atScale:
兩個方法。另外 maximumZoomScale和minimumZoomScale 兩個屬性要不一樣。

幾個屬性介紹

tracking
當 touch 後還沒有拖動的時候值是YES,否則NO

zoomBouncing
當內容放大到最大或者最小的時候值是 YES,否則 NO

zooming
當正在縮放的時候值是 YES,否則 NO

decelerating
當滾動後,手指放開但是還在繼續滾動中。這個時候是 YES,其它時候是 NO

decelerationRate
設定手指放開後的減速率

maximumZoomScale
一個浮點數,表示能放最大的倍數

minimumZoomScale 
一個浮點數,表示能縮最小的倍數

pagingEnabled
當值是 YES 會自動滾動到 subview 的邊界。預設是NO

scrollEnabled
決定是否可以滾動

delaysContentTouches
是個布林值,當值是 YES 的時候,使用者觸碰開始,scroll view要延遲一會,看看是否使用者有意圖滾動。假如滾動了,那麼捕捉 touch-down 事件,否則就不捕捉。假如值是NO,當使用者觸碰, scroll view 會立即觸發 touchesShouldBegin:withEvent:inContentView:,預設是 YES

canCancelContentTouches
當值是 YES 的時候,使用者觸碰後,然後在一定時間內沒有移動,scrollView 傳送 tracking events,然後使用者移動手指足夠長度觸發滾動事件,這個時候,scrollView 傳送了 touchesCancelled:withEvent: 到 subview,然後 scroView 開始滾動。假如值是 NO,scrollView 傳送 tracking events 後,就算使用者移動手指,scrollView 也不會滾動。

contentSize
裡面內容的大小,也就是可以滾動的大小,預設是0,沒有滾動效果。

showsHorizontalScrollIndicator
滾動時是否顯示水平滾動條

showsVerticalScrollIndicator
滾動時是否顯示垂直滾動條

bounces
預設是 yes,就是滾動超過邊界會反彈有反彈回來的效果。假如是 NO,那麼滾動到達邊界會立刻停止。

bouncesZoom
和 bounces 類似,區別在於:這個效果反映在縮放上面,假如縮放超過最大縮放,那麼會反彈效果;假如是 NO,則到達最大或者最小的時候立即停止。

directionalLockEnabled
預設是 NO,可以在垂直和水平方向同時運動。當值是 YES 時,假如一開始是垂直或者是水平運動,那麼接下來會鎖定另外一個方向的滾動。 假如一開始是對角方向滾動,則不會禁止某個方向

indicatorStyle
滾動條的樣式,基本只是設定顏色。總共3個顏色:預設、黑、白

scrollIndicatorInsets
設定滾動條的位置

最後加上,我剛定的一個例子,可以縮放,及對使用的代理方法加了註釋


//  ScrollViewViewController.m

//  ScrollView

//

//  Created by ch_soft on 11-11-8.

//  Copyright 2011 __MyCompanyName__. All rights reserved.

//


#import"ScrollViewViewController.h"

#import"CustomA.h"

#import"CustomB.h"


@implementation ScrollViewViewController


- (void)didReceiveMemoryWarning

{

   // Releases the view if it doesn't have a superview.

    [superdidReceiveMemoryWarning];

    

   // Release any cached data, images, etc that aren't in use.

}


#pragma mark - View lifecycle



// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad

{

   scrollview =[[UIScrollViewalloc]initWithFrame:CGRectMake(50,0,200,400)];

    scrollview.contentSize=CGSizeMake(400,400);

   scrollview.backgroundColor=[UIColororangeColor];

   scrollview.pagingEnabled=YES;//是否自己動適應

    

   viewA=[[CustomAalloc]initWithFrame:CGRectMake(50,0,100,400)];

   viewA.backgroundColor=[UIColorblueColor];

    [scrollviewaddSubview:viewA];

    [viewArelease];

    

    CustomB * viewB=[[CustomB allocinitWithFrame:CGRectMake(250,0,100,400)];

    viewB.backgroundColor=[UIColoryellowColor];

    [scrollviewaddSubview:viewB];

    [viewB release];

    

    [self.viewaddSubview:scrollview];

   scrollview.maximumZoomScale=2.0;

   scrollview.minimumZoomScale=0.5;

//    scrollview.decelerationRate=1;

   scrollview.delegate=self;

   //canCancelContentTouches:YES-移動手指足夠長度觸發滾動事件,NO-scrollView傳送 tracking events 後,就算使用者移動手指,scrollView也不會滾動。

   scrollview.canCancelContentTouches=NO;

    

    //當值是 YES的時候,使用者觸碰開始.要延遲一會,看看是否使用者有意圖滾動。假如滾動了,那麼捕捉 touch-down事件,否則就不捕捉。假如值是NO,當使用者觸碰, scroll view會立即觸發

   scrollview.delaysContentTouches=YES;

    [scrollviewrelease];

    [superviewDidLoad];

}



#pragma mark UIScrollViewDelegate

//只要滾動了就會觸發

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;   

{

//    NSLog(@" scrollViewDidScroll");

    NSLog(@"ContentOffset  x is  %f,yis %f",scrollView.contentOffset.x,scrollView.contentOffset.y);

}

//開始拖拽檢視

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;   

{

   NSLog(@"scrollViewWillBeginDragging");

}

//完成拖拽

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; 

{

   NSLog(@"scrollViewDidEndDragging");

}

//將開始降速時

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;   

{

   NSLog(@"scrollViewWillBeginDecelerating");

}


//減速停止了時執行,手觸控時執行執行

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;   

{

   NSLog(@"scrollViewDidEndDecelerating");

}

//滾動動畫停止時執行,程式碼改變時出發,也就是setContentOffset改變時

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;

{

   NSLog(@"scrollViewDidEndScrollingAnimation");

}

//設定放大縮小的檢視,要是uiscrollviewsubview

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;   

{

   NSLog(@"viewForZoomingInScrollView");

    return viewA;

}

//完成放大縮小時呼叫

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale; 

{

    viewA.frame=CGRectMake(50,0,100,400);

   NSLog(@"scale between minimum and maximum. called after any 'bounce' animations");

}// scale between minimum and maximum. called after any 'bounce' animations


//如果你不是完全滾動到滾軸檢視的頂部,你可以輕點狀態列,那個可視的滾軸檢視會一直滾動到頂部,那是預設行為,你可以通過該方法返回NO來關閉它

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;   

{

    NSLog(@"scrollViewShouldScrollToTop");

   returnYES;

}


- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;     

{

    NSLog(@"scrollViewDidScrollToTop");

}




- (void)viewDidUnload

{

    [super viewDidUnload];

   // Release any retained subviews of the main view.

   // e.g. self.myOutlet = nil;

}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

{

   // Return YES for supported orientations

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}


@end


完畢,如發現在有新的內容再更新

相關文章