W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
對于一個未轉(zhuǎn)換的圖層,它的bounds
和它的frame
是一樣的,frame
屬性是由bounds
屬性自動計算而出的,所以更改任意一個值都會更新其他值。
但是如果你只想顯示一個大圖層里面的一小部分呢。比如說,你可能有一個很大的圖片,你希望用戶能夠隨意滑動,或者是一個數(shù)據(jù)或文本的長列表。在一個典型的iOS應(yīng)用中,你可能會用到UITableView
或是UIScrollView
,但是對于獨立的圖層來說,什么會等價于剛剛提到的UITableView
和UIScrollView
呢?
在第二章中,我們探索了圖層的contentsRect
屬性的用法,它的確是能夠解決在圖層中小地方顯示大圖片的解決方法。但是如果你的圖層包含子圖層那它就不是一個非常好的解決方案,因為,這樣做的話每次你想『滑動』可視區(qū)域的時候,你就需要手工重新計算并更新所有的子圖層位置。
這個時候就需要CAScrollLayer
了。CAScrollLayer
有一個-scrollToPoint:
方法,它自動適應(yīng)bounds
的原點以便圖層內(nèi)容出現(xiàn)在滑動的地方。注意,這就是它做的所有事情。前面提到過,Core Animation并不處理用戶輸入,所以CAScrollLayer
并不負責將觸摸事件轉(zhuǎn)換為滑動事件,既不渲染滾動條,也不實現(xiàn)任何iOS指定行為例如滑動反彈(當視圖滑動超多了它的邊界的將會反彈回正確的地方)。
讓我們來用CAScrollLayer
來常見一個基本的UIScrollView
替代品。我們將會用CAScrollLayer
作為視圖的宿主圖層,并創(chuàng)建一個自定義的UIView
,然后用UIPanGestureRecognizer
實現(xiàn)觸摸事件響應(yīng)。這段代碼見清單6.10. 圖6.11是運行效果:ScrollView
顯示了一個大于它的frame
的UIImageView
。
清單6.10 用CAScrollLayer
實現(xiàn)滑動視圖
#import "ScrollView.h"
#import @implementation ScrollView
+ (Class)layerClass
{
return [CAScrollLayer class];
}
- (void)setUp
{
//enable clipping
self.layer.masksToBounds = YES;
//attach pan gesture recognizer
UIPanGestureRecognizer *recognizer = nil;
recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self addGestureRecognizer:recognizer];
}
- (id)initWithFrame:(CGRect)frame
{
//this is called when view is created in code
if ((self = [super initWithFrame:frame])) {
[self setUp];
}
return self;
}
- (void)awakeFromNib {
//this is called when view is created from a nib
[self setUp];
}
- (void)pan:(UIPanGestureRecognizer *)recognizer
{
//get the offset by subtracting the pan gesture
//translation from the current bounds origin
CGPoint offset = self.bounds.origin;
offset.x -= [recognizer translationInView:self].x;
offset.y -= [recognizer translationInView:self].y;
//scroll the layer
[(CAScrollLayer *)self.layer scrollToPoint:offset];
//reset the pan gesture translation
[recognizer setTranslation:CGPointZero inView:self];
}
@end
圖6.11 用UIScrollView
創(chuàng)建一個湊合的滑動視圖
不同于UIScrollView
,我們定制的滑動視圖類并沒有實現(xiàn)任何形式的邊界檢查(bounds checking)。圖層內(nèi)容極有可能滑出視圖的邊界并無限滑下去。CAScrollLayer
并沒有等同于UIScrollView
中contentSize
的屬性,所以當CAScrollLayer
滑動的時候完全沒有一個全局的可滑動區(qū)域的概念,也無法自適應(yīng)它的邊界原點至你指定的值。它之所以不能自適應(yīng)邊界大小是因為它不需要,內(nèi)容完全可以超過邊界。
那你一定會奇怪用CAScrollLayer
的意義到底何在,因為你可以簡單地用一個普通的CALayer
然后手動適應(yīng)邊界原點啊。真相其實并不復(fù)雜,UIScrollView
并沒有用CAScrollLayer
,事實上,就是簡單的通過直接操作圖層邊界來實現(xiàn)滑動。
CAScrollLayer
有一個潛在的有用特性。如果你查看CAScrollLayer
的頭文件,你就會注意到有一個擴展分類實現(xiàn)了一些方法和屬性:
- (void)scrollPoint:(CGPoint)p;
- (void)scrollRectToVisible:(CGRect)r;
@property(readonly) CGRect visibleRect;
看到這些方法和屬性名,你也許會以為這些方法給每個CALayer
實例增加了滑動功能。但是事實上他們只是放置在CAScrollLayer
中的圖層的實用方法。scrollPoint:
方法從圖層樹中查找并找到第一個可用的CAScrollLayer
,然后滑動它使得指定點成為可視的。scrollRectToVisible:
方法實現(xiàn)了同樣的事情只不過是作用在一個矩形上的。visibleRect
屬性決定圖層(如果存在的話)的哪部分是當前的可視區(qū)域。如果你自己實現(xiàn)這些方法就會相對容易明白一點,但是CAScrollLayer
幫你省了這些麻煩,所以當涉及到實現(xiàn)圖層滑動的時候就可以用上了。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: