UIScrollView為了顯示多于一個屏幕的內容或者超過你能放在內存中的內容。Scroll View為你處理縮小放大手勢,UIScrollView實現了這些手勢,并且替你處理對于它們的探測和回應。其中需要注意的子類是UITableView以及UITextView(用來顯示大量的文字)。還有一個UIWebView,盡管那不是UIScrollView的直接子類,它適用UIScrollView去顯示網頁內容contentsize是內容的寬和高,contentsize.width是內容的寬度,contentsize.heght是高度,contentsize是UIScrollView的一個屬性,它是一個CGSize,是由核心圖形所定義的架構,那定義了你可以滾軸內容的寬度和高度,你也可以添加可以上下滾動的額外區域。第一種方法是你可以通過添加內容的大小來完成。另外一個比較動態的選擇是UIScrollView的另一個屬性contentInset,contentInset增加你在contentsize中指定的內容能夠滾動的上下左右區域數量contentInset.top以及contentInset.buttom分別表示上面和下面的距離。
在滾軸視圖中,有一個叫做ContentOffset的屬性跟蹤UIScrollView的具體位置,你能夠自己獲取和設置它,ContentOffset是你當前可視內容在滾軸視圖邊界的左上角那個點。如圖:
可以看出,ContentOffset內容中的那個點不是從contentInset的左上角開始的,而是內容的左上角,此時的ContentOffset是正值,但有時也是負值,如下圖所示:
使用一個ScrollView
創建一個UIScrollView
擴展Scroll View 的行為
通過子類化擴展Scroll View 的行為
應用程序的邏輯和行為變成了視圖本身的一部分,就像,你可能有一些定制的滾軸邏輯,,在那你只在意一個視圖控制,但你想在不同地方重復使用你的滾軸視圖,如果你必須為每個都子類化,你最后會有很多不同的滾軸視圖子類以及在視圖中的特定應用邏輯。
編寫很多子類是很沉悶的事情,你最后會有很多無法重復使用的單獨視圖,而MVC的視圖部分的一個重點是視圖是可以在不同的控制器和不同的模式之中重復使用的,如果我們把所有邏輯都放在視圖中,它減少了可復用性。
你的代碼變得很牢固地配對在一起,它實際上變成了超類的一部分,你無法從UIScrollView中析取它,之后用其它東西代替,如果它在你控制器中且為控制器的一部分,在之后更容易改變它工作的方式和重新安排你應用程序的一些部分。
通過委派來擴展Scroll View 的行為(常用的)
委派是一個單獨的對象,協議,定義了委派會實現的一系列功能的Objective-C協議,它創建了一系列很清晰的撤銷點,在那里你能定制行為和外觀。它在這些對象之間保持了松散的配對,視圖本身與視圖控制器或任何其它的控制器對象,委派不是滾軸視圖的直接子類,它比起牢固配對的子類更加的松散。
理論篇
在滾動的過程中,實際上就是contentOffset的值在不斷變化,當手指觸摸后,UIScrollView會暫時攔截觸摸事件,使用一個計時器。假如在計時器到點后沒有發生手指移動事件,那么UIScrollView發送 tracking events 到被點擊的 subview 上面。如果在計時器到點前發生了移動事件,那么UIScrollView取消 tracking 然后自己發生滾動。
可以重載子類
屬性篇
方法篇
直接上代碼看
//減速停止了時執行,手觸摸時執行
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
{
NSLog(@"scrollViewDidEndDecelerating");
}
//滾動動畫停止時執行,代碼改變時出發,也就是setContentOffset改變時
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;
{
NSLog(@"scrollViewDidEndScrollingAnimation");
}
//設置放大縮小的視圖,要是uiscrollview的subview
- (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");
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end
基于AotoLayout的控件懸停
在很多的電商類的APP中我們經常會用到一種滑動懸停的效果,所以這次嘗試著利用AutoLayout來實現這種效果。話不多說先上圖
效果:
效果上過了,還是理順下思路上吧。從效果圖上不難發現我們的程序是基于UIScrollerView的。界面上的展示同樣都是UIScrollView的子控件。當然了難點也就是基于UIScrollerView的內部子控件的布局以及AutoLayout約束的修改。
我們看一下我們的需要的一些基本的控件布局:
好了,現在開始開始搭建新的項目了,首先在Storyboard上搭建最基本的布局,并將控件基本布局到相應的位置,以備我們更方便的添加約束。
到了這里就開始對我們的控件添加基本的約束了從上開始吧。上面的控件我們能確定是UIImageView的heigth以及top、left以及rihgt。至于bottom到了后面會著重設置的。
然后繼續來操作懸停的View。這個View因為處在兩個view的中間所以我們要暫時確定height以及left和right的約束就足夠了了
終于到最后一個UIImageView了,同樣的能確定的是height、right、left以及bottom這四項。
到了這里針對單個的控件的布局基本完成了,細心的你可能會發現以上的操作都沒有進行關聯以及沒有對width進行約束。那么下面我們就要開始進行三者的關聯以及width上的設置。
因為懸停的view處與兩個imageView的中間,所以我們只需要對它進行處理就好了
其實這兩個約束完全是可以在設置懸停view的時候的添加,之所以在這里添加是我們在后面的控制器會用到這兩個約束,為了好辨認我們就給他們定義上別名:
然后我們按住command選擇我們的三個控件然后按住control拖向scrollView的父控件view設置等width。
好了,到了這里我們的約束已經不會再報錯了,然后在邏輯上也是基本是通順的了,但是對于我們懸停的功能來說就少了關鍵的一個環節那么就是一旦懸停view懸停了,那么它與上下兩個imageView的約束要怎么處理呢?所以我們還需要一個輔助的約束用來懸停之后的關聯處理
添加之后我們給這個約束起個別名hidden懸停,不過細心的你一定會發現添加之后會sb會提示出有沖突的約束,那么我們只需要對我們剛剛添加的約束進行一下操作就OK了
好了,到了這里我們在AutoLayout上要做的事情就這些了,下面我們就可以安心的寫代碼了。
[scrollView addSubview:self.centreView];
//記住一定要先添加到scrollView上之后在修改約束的內容,不然添加的約束會不成,因為系統無法建立他們之間的聯系。
self.hiddenConstraint.active = NO;
self.topConstraint.active = YES;
self.bottomConstraint.active = YES;
}
//等比例的伸縮
CGFloat scale= 1-(offsetY/60);
scale = (scale>=1)?scale :1;
self.topImageView.transform = CGAffineTransformMakeScale(scale, scale);
}
在UIScrollView里面布局子控件,sb里面默認是是需要子控件的尺寸以及子控件與UIScrollView之間的間距來計算出scroller的conentSize的。所以這就是上面的子控件要與父控件來等寬的原因了。
UIScrollView的frame應該通過子控件以外的其他控件來計算。
新聞熱點
疑難解答