有没有办法让 CALayer 的动作字典永久优先于其 UIView 委托?
Posted
技术标签:
【中文标题】有没有办法让 CALayer 的动作字典永久优先于其 UIView 委托?【英文标题】:Is there a way to give a CALayer's action dictionary permanent precendece over its UIView delegate? 【发布时间】:2012-01-28 21:59:06 【问题描述】:我有以下情况:
从视图控制器中,我开始创建任意数量的透明 UIButton,它们在控制器的主视图上调整 UIView 的外观和消失。现在,当我的“放大”和“缩小”方法被调用时,有代码用于修改两个 CALayer 属性的默认动画(实际上只是持续时间)。然后每次发生操作时都会调用此代码。但我想在图层内设置一次动画代码,而不是在缩放方法中。在我展示了基本思想之后,我会进一步解释:
按钮/传感器创建代码太长,无法发布(与实际问题无关),但与此伪代码类似:
- (void) createSensors:[number of sensors]
for(number of sensors)
create UIVIew with some content;
create transparent UIBUtton as sensor and place somewhere in main view;
calculate a transform to "shrink" the UIView's layer to the size and position of the button.
apply transform;
set the UIVIew's layer opacity to 0;
add UIVIew to main view
(but the rest of my interface is in a container view, so I can dim the screen and have this view displayed in a modal-like way.)
do some tagging so the button's tag can later be used to retrieve this view and transform.
现在,当单击传感器时,我对与传感器/视图关联的视图执行“放大”。我实际上将屏幕调暗为白色,并为视图(图层的实际位置)设置动画并缩放到屏幕中心。在单击视图中的按钮时,我会做相反的事情来关闭它。这是代码:
- (void)animateZoomIn:(UIButton*)sender
NSString *sourceTagKey = [NSString stringWithFormat:@"%i",sender.tag];
AnimationSettings *settings = [zoomTransforms objectForKey:sourceTagKey];
UIView *newBox = [[self.view subviews] objectAtIndex:sender.tag];
activeZoomBox = newBox;
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
[mainCanvas.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.duration = 1;
[activeZoomBox.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
a.duration = .5;
[activeZoomBox.layer addAnimation:a forKey:@"transform"];
[mainCanvas setUserInteractionEnabled:NO];
if([settings wantsBackgroundFade])
[mainCanvas.layer setOpacity:.2];
[activeZoomBox.layer setOpacity:1];
[activeZoomBox.layer setTransform:CATransform3DIdentity];
- (void)animateZoomOut:(UIButton*)sender
NSString *sourceTagKey = [NSString stringWithFormat:@"%i",sender.tag];
AnimationSettings *settings = [zoomTransforms objectForKey:sourceTagKey];
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
[mainCanvas.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.duration = 1;
[activeZoomBox.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
a.duration = .5;
[activeZoomBox.layer addAnimation:a forKey:@"transform"];
[mainCanvas setUserInteractionEnabled:YES];
if([settings wantsBackgroundFade])
[mainCanvas.layer setOpacity:1];
[activeZoomBox.layer setOpacity:0];
[activeZoomBox.layer setTransform:[settings transform]];
那么,问题来了:
我不想有这种代码:
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
[mainCanvas.layer addAnimation:a forKey:@"opacity"];
在动作方法中。我宁愿更换一次动画,并使其对创建的每个图层和 mainCanvas 视图“永久”。例如,我宁愿在控制器的 init 方法中使用此代码一次,然后忘记它:
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
NSMutableDictionary *animations = [NSMutableDictionary dictionaryWithDictionary:[mainCanvas.layer actions]];
[animations setObject:a forKey:@"opacity"];
[mainCanvas.layer setActions:animations];
然后,每当我调用 [mainCanvas setOpacity:] 时,默认情况下它会持续 0.4 秒。使用无委托的 CALayer 就可以了。但在这种情况下,我的图层将其视图作为委托,优先于操作字典,我有点需要将视图作为委托..
那么有没有办法让图层仍然响应字典?如果不是,那么“永久替换”或向这些图层添加动画的最佳方法是什么,以便动画包含在图层对象中(这就是为什么我不想覆盖视图的 CAAction 委托方法的原因协议)?
【问题讨论】:
【参考方案1】:为什么不直接覆盖 UIView 上的 -actionForLayer:forKey:
以在重要键上提供您想要的操作(并为其他键调用 super)?无法更改优先级,因此您唯一的选择是实现 -actionForLayer:forKey:
或使用手动动画。
【讨论】:
以上是关于有没有办法让 CALayer 的动作字典永久优先于其 UIView 委托?的主要内容,如果未能解决你的问题,请参考以下文章