你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS 為移動動畫中的View添加touch事件

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

編輯:IOS開發綜合
對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的順序不同,開始看到的結果也不同:\\
左邊是先設置的anchZ喎?/kf/ware/vc/" target="_blank" class="keylink">vclBvaW501NnJ6NbDZnJhbWWjrNPSsd/Kx8/gt7SjrL/J0tS/tLW9yOe5+8rHz8jJ6NbDYW5jaG9yUG9pbnS1xLuwo6zU2rjVv6rKvL7NxNy1w7W91f3It7XEveG5+6OsvLRwb3NpdGlvbs6qMKOsMKGjtavI57n7ysfJ6NbDYm91bmRztcS7sL7NsrvTw9Xiw7TC6bezwcujrMuz0PLO3sv5zr2ho87S1NrV4sDv1q7L+dLU0qrJ6NbDYW5jaG9yUG9pbnSjrMrH0vLOqtTauvPD5rXEQ0FLZXlmcmFtZUFuaW1hdGlvbr2r08Nwb3NpdGlvbsC01/a2r7uto6zI57n7YW5jaG9yUG9pbnTOqsSsyM/WtaOovLQwLjUsMC41o6m1xLuwo6zU2ravu63W0L2ru+Gz9s/W0ru49nihonnW4dK7sOu1xMar0sajrL7Nz/HV4tH5o7o8aW1nIHNyYz0="/uploadfile/Collfiles/20140804/2014080408183158.png" width="319" height="179" alt="\" />
下面用一張圖解釋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下載
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved