iOS 為移動動畫中的View添加touch事件

來源:互聯網
上載者:User

iOS 為移動動畫中的View添加touch事件
對Core Animation來說,不管是顯式動畫還是隱式動畫,對其設定frame都是立即設定的,比如說給一個UIView做移動動畫,雖然看起來frame在持續改變,但其時它的frame已經是最終值了,這種情況下,哪怕這個UIView是UIButton的執行個體,其觸發touch事件的範圍還是最終frame的地方。比如一個Button的frame是(0,0,100,100),要把它從0,0移動到200,200,在這種情況下:
如果你使用的是顯式動畫(CAKeyframeAnimation和CABasicAnimation),是通過指定path或values來進行動畫的,它的frame並沒有改變,touch範圍還是(0,0,100,100)這個範圍內如果你使用的是隱式動畫,是通過設定frame來進行動畫的,那麼它的touch範圍就是(200,200,100,100)這個範圍內如果我們要為移動動畫中的View添加touch事件,就需要在後面用到hitTest。我們先建立一個動畫Layer:

CGSize layerSize = CGSizeMake(100, 100);CALayer *movingLayer = [CALayer layer];movingLayer.bounds = CGRectMake(0, 0, layerSize.width, layerSize.height);[movingLayer setBackgroundColor:[UIColor orangeColor].CGColor];movingLayer.anchorPoint = CGPointMake(0, 0);[self.view.layer addSublayer:movingLayer];self.movingLayer = movingLayer;
這裡面只有anchorPoint重要一些,因為anchorPoint能影響position的取值,對Layer來說,frame是抽象的,只有bounds和position是真實存在的,並且設定frame和設定anchorPoint的順序不同,開始看到的結果也不同:
左邊是先設定的anchorPoint再設定frame,右邊是相反,可以看到如果是先設定anchorPoint的話,在剛開始就能得到正確的結果,即position為0,0。但如果是設定bounds的話就不用這麼麻煩了,順序無所謂。我在這裡之所以要設定anchorPoint,是因為在後面的CAKeyframeAnimation將用position來做動畫,如果anchorPoint為預設值(即0.5,0.5)的話,在動畫中將會出現一個x、y軸一半的位移,就像這樣:
下面用一張圖解釋anchorPoint的取值:
position是以anchorPoint為原點的,預設這個原點在中心位置,自然就會出現x、y軸的位移,其實只要我在動畫中將position做個位移就不用設定anchorPoint,但是我覺得動畫從0到終點更直觀一些,所以這才是我設定anchorPoint的原因,並不是說非設不可。最後用一個weak屬性引用動畫Layer並把這個Layer添加到self.view.layer中。接下來是動畫部分:
CAKeyframeAnimation *moveLayerAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];//moveLayerAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];//moveLayerAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(320 - self.movingLayer.bounds.size.width, 0)];moveLayerAnimation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],                              [NSValue valueWithCGPoint:CGPointMake(320 - self.movingLayer.bounds.size.width, 0)]];moveLayerAnimation.duration = 2.0;moveLayerAnimation.autoreverses = YES;moveLayerAnimation.repeatCount = INFINITY;moveLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];[self.movingLayer addAnimation:moveLayerAnimation forKey:@"move"];
如果是用CABasicAnimation做動畫,則用fromValue及toValue替換setValues,timingFunction直接用線性,不用做其他變換,關於這個屬性的預置值,我在另一篇博文中有提到。
接下來為self.view添加手勢識別:
........    self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click:)];    [self.view addGestureRecognizer:self.tapGesture];}-(void)click:(UITapGestureRecognizer *)tapGesture {    CGPoint touchPoint = [tapGesture locationInView:self.view];    if ([self.movingLayer.presentationLayer hitTest:touchPoint]) {        NSLog(@"presentationLayer");    }}
我在最開始的時候有提到,動畫的過程只是看起來是動態變換的,其內部的值已經是固定的了。接下來簡單說下Core Animation,Core Animation用三個集合來完成動畫:Layer Tree、Presentation Tree、Render Tree。Layer Tree用來儲存Layer最終的值,即不考慮動畫的發生,你只要對一個Layer進行了一些諸如backgroundColor、position、alpha之類的賦值,其Layer Tree中儲存的值立刻改變;Presentation Tree用來儲存所有的要在動畫過程中顯示的值,與Layer Tree相反;Render Tree專門用來渲染Presentation Tree中的值,也是與Core Animation互動的唯一紐帶,這一過程被系統隱藏了,我們不用管也沒辦法管。這就是說Layer Tree與Presentation Tree其實都相當於是模型對象,只儲存Layer的狀態,當我們要讀取動畫進行中的狀態的時候,調用layer的presentationLayer屬性就可以了,這個屬性從Presentation Tree中返回代表當前動態狀態的Layer,接下來調用Layer的hitTest方法就能判斷是不是一次有效點擊了。
Demo下載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.