【问题标题】:Update view's frame while it's being animated在动画时更新视图的框架
【发布时间】:2016-10-15 13:34:12
【问题描述】:

我正在做这样的动画:

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    animation.duration = 100.0;
    animation.path = self.animationPath.CGPath;
    [view.layer addAnimation:animation forKey:@"animation"];

工作正常,但是,现在尝试检测在屏幕上移动的对象上的触摸时会失败:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    for (UIView* subview in self.subviews ) {
        if ( [subview hitTest:[self convertPoint:point toView:subview] withEvent:event] != nil ) {
            [self handleTap];
            return YES;
        }
    }
    return NO;
}

它失败是因为视图的框架不再与它在动画时在屏幕上的明显位置相同。如何让pointInside 使用正在动画的视图?

【问题讨论】:

    标签: ios uiview core-animation caanimation cakeyframeanimation


    【解决方案1】:

    简短的回答:你不能。在 UIView 和 Core Animation 动画中,视图/层实际上并没有移动,因为它的位置似乎是动画。相反,有一个“表示层”可以在动画对象移动时绘制它。

    如果您想在位置动画“飞行”时使对象可点击,您必须将点击手势识别器放在跨越视图将经过的整个区域的超级视图上,然后在表示层上进行点击测试正在动画的对象。

    编辑:

    我在 Github 上有一个名为 iOS CAAnimation Group demo 的项目,该项目演示了如何在表示层上使用命中测试来检测沿复杂路径动画的视图上的点击。

    代码是用 Objective-C 编写的,但它仍然应该是概念和技术的说明。如果您无法理解 Objective-C 代码,请告诉我。我在 Swift 方面表现不错,尽管我仍然主要使用 Objective-C 来支付账单,所以这是我最了解的语法。

    【讨论】:

      【解决方案2】:

      这是我的代码

      #import "ViewController.h"
      
      @interface ViewController ()
      @property (weak, nonatomic) IBOutlet AnimatableView *animableView;
      @end
      
      @implementation ViewController
      
      - (void)animateAlongPath
      {
          UIBezierPath * path = [UIBezierPath bezierPathWithRect:self.view.frame];
      
          CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
          animation.duration = 10;
          animation.path = path.CGPath;
          animation.removedOnCompletion = NO;
          animation.fillMode = @"kCAFillModeForwards";
          [self.animableView.layer addAnimation:animation forKey:@"animation"];
      }
      
      - (void)viewDidLoad {
          [super viewDidLoad];
          // Do any additional setup after loading the view, typically from a nib.
      }
      
      - (void)didReceiveMemoryWarning {
          [super didReceiveMemoryWarning];
          // Dispose of any resources that can be recreated.
      }
      - (IBAction)animate:(id)sender {
          [self animateAlongPath];
      }
      
      -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
      {
          UITouch *touch = [touches anyObject];
          CGPoint location = [touch locationInView: [touch view]];
      
          CALayer * selectedlayer = (CALayer*)[self.animableView.layer.presentationLayer hitTest:location];
          if(selectedlayer != nil)
              NSLog(@"touched");
          else
              NSLog(@"dont touched");
      }
      
      
      @end
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 2021-09-04
        • 2021-09-01
        • 2015-05-04
        • 2016-02-22
        • 1970-01-01
        • 1970-01-01
        • 2011-10-02
        • 1970-01-01
        • 2014-06-09
        相关资源
        最近更新 更多