将子图层定位在动画UIView的中心

时间:2015-04-04 00:12:02

标签: ios core-animation calayer anchorpoint

我有一个UIView形状像一个扩展和收缩的圆圈。 我需要在其中心放置一个子图层,其大小与动画相同。下面的代码包含四个示例视图,显示我尝试过的内容。它可以按原样复制和粘贴。

  1. 第一个UIView是一个没有动画的。它的子层位于其中心,但必须相对于UIView的原点定位。当UIView的边界和原点在动画期间发生变化时,这是一个问题。
  2. 第二个UIView有两个动画:一个用于@"bounds",另一个用于@"cornerRadius"。这种安排导致子层终止于屏幕的原点(左上角)。
  3. 第三个UIView也有两个动画:这次是@"bounds.size"@"cornerRadius"。子层保持相同的大小,这是好的,但它不会留在UIView的中心。我尝试使用[thirdView.layer setNeedsDisplayOnBoundsChange:YES];来补偿边界变化,但它没有用。我也试过thirdView.contentMode = UIViewContentModeRedraw;
  4. 第四个UIView有一个@"transform.scale"的动画,就扩展动画来说,它看起来效率更高一些。子层像我想要的那样停留在UIView的中心,但它不会保持相同的大小。我需要让子层的大小独立,因为我打算给它制作动画。
  5. 这是所有代码。它看起来很多,但它是一些非常简单的东西。

        - (void)viewDidLoad {
        [super viewDidLoad];
        float screenWidth = [UIScreen mainScreen].bounds.size.width;
        float screenHeight = [UIScreen mainScreen].bounds.size.height;
    
        UIView * firstView = [[UIView alloc] initWithFrame:CGRectMake((screenWidth/4) - 25, (screenHeight/4) - 25, 50, 50)];
        // [firstView.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
        firstView.backgroundColor = [UIColor blueColor];
        firstView.layer.cornerRadius = 25;
        NSLog(@"firstView anchor point %@", [NSValue valueWithCGPoint:firstView.layer.anchorPoint]);
    
        CALayer * firstLayer = [CALayer layer];
        firstLayer.backgroundColor = [UIColor redColor].CGColor;
        [firstView.layer addSublayer:firstLayer];
        firstLayer.bounds = CGRectMake(0,0, 30, 30);
        firstLayer.cornerRadius = 15;
        firstLayer.position = CGPointMake(firstView.bounds.size.width/2,        firstView.bounds.size.height/2);
        [self.view addSubview:firstView];
    
    
        UIView * secondView = [[UIView alloc] initWithFrame:CGRectMake((screenWidth*3/4) - 25, (screenHeight/4) - 25, 50, 50)];
        secondView.backgroundColor = [UIColor blueColor];
        secondView.layer.cornerRadius = 25;
    
        CALayer * secondLayer = [CALayer layer];
        secondLayer.backgroundColor = [UIColor redColor].CGColor;
        [secondView.layer addSublayer:secondLayer];
        secondLayer.bounds = CGRectMake(0, 0, 30, 30);
        secondLayer.cornerRadius = 15;
        secondLayer.position = CGPointMake(secondView.bounds.size.width/2, secondView.bounds.size.height/2);
    
        CABasicAnimation * secondViewBoundsAnimation;
        secondViewBoundsAnimation = [CABasicAnimation animation];
        secondViewBoundsAnimation.keyPath = @"bounds";
        secondViewBoundsAnimation.fromValue = [NSValue valueWithCGRect:CGRectMake((screenWidth*3/4) - 25, (screenHeight/4) - 25, 50, 50)];
        secondViewBoundsAnimation.toValue = [NSValue valueWithCGRect:CGRectMake((screenWidth*3/4) - 50, (screenHeight/4) - 50, 100, 100)];
    
        CABasicAnimation * secondViewCornerRadiusAnimation;
        secondViewCornerRadiusAnimation = [CABasicAnimation animation];
        secondViewCornerRadiusAnimation.keyPath = @"cornerRadius";
        secondViewCornerRadiusAnimation.fromValue = @25;
        secondViewCornerRadiusAnimation.toValue = @50;
    
        CAAnimationGroup * secondViewAnimationGroup;
        secondViewAnimationGroup = [CAAnimationGroup animation];
        secondViewAnimationGroup.animations = [NSArray arrayWithObjects:secondViewBoundsAnimation, secondViewCornerRadiusAnimation, nil];
        secondViewAnimationGroup.duration = 1.5;
        secondViewAnimationGroup.repeatCount = HUGE_VALF;
        secondViewAnimationGroup.autoreverses = YES;
    
        [secondView.layer addAnimation:secondViewAnimationGroup forKey:@"secondViewAnimation"];
    
        [self.view addSubview:secondView];
    
    
        UIView * thirdView;
        // [thirdView.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
        thirdView = [[UIView alloc] initWithFrame:CGRectMake((screenWidth/4) - 25, (screenHeight*3/4) -25, 50, 50)];
        thirdView.backgroundColor = [UIColor blueColor];
        thirdView.layer.cornerRadius = 25;
        NSLog(@"thirdView anchor point %@", [NSValue valueWithCGPoint:thirdView.layer.anchorPoint]);
    
        CALayer * thirdLayer = [CALayer layer];
        thirdLayer.backgroundColor = [UIColor redColor].CGColor;
        [thirdView.layer addSublayer:thirdLayer];
        thirdLayer.bounds = CGRectMake(0, 0, 30, 30);
        thirdLayer.cornerRadius = 15;
        thirdLayer.position = CGPointMake(thirdView.bounds.size.width/2, thirdView.bounds.size.height/2);
    
        CABasicAnimation * thirdViewSizeAnimation;
        thirdViewSizeAnimation = [CABasicAnimation animation];
        thirdViewSizeAnimation.keyPath = @"bounds.size";
        thirdViewSizeAnimation.fromValue = [NSValue    valueWithCGSize:CGSizeMake(50, 50)];
        thirdViewSizeAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
    
        CABasicAnimation * thirdViewCornerRadiusAnimation;
        thirdViewCornerRadiusAnimation = [CABasicAnimation animation];
        thirdViewCornerRadiusAnimation.keyPath = @"cornerRadius";
        thirdViewCornerRadiusAnimation.fromValue = @25;
        thirdViewCornerRadiusAnimation.toValue = @50;
    
        CAAnimationGroup * thirdViewAnimationGroup;
        thirdViewAnimationGroup = [CAAnimationGroup animation];
        thirdViewAnimationGroup.animations = [NSArray arrayWithObjects:thirdViewSizeAnimation, thirdViewCornerRadiusAnimation, nil];
        thirdViewAnimationGroup.duration = 1.5;
        thirdViewAnimationGroup.repeatCount = HUGE_VALF;
        thirdViewAnimationGroup.autoreverses = YES;
    
        //    thirdView.contentMode = UIViewContentModeRedraw;
        //    [thirdView.layer setNeedsDisplayOnBoundsChange:YES];
        [thirdView.layer addAnimation:thirdViewAnimationGroup forKey:@"thirdViewAnimation"];
    
        [self.view addSubview:thirdView];
    
    
    
        UIView * fourthView = [[UIView alloc] initWithFrame:CGRectMake((screenWidth*3/4) - 25, (screenHeight*3/4) - 25, 50, 50)];
        fourthView.backgroundColor = [UIColor blueColor];
        fourthView.layer.cornerRadius = 25;
    
    
        CALayer * fourthLayer = [CALayer layer];
        fourthLayer.backgroundColor = [UIColor redColor].CGColor;
        [fourthView.layer addSublayer:fourthLayer];
        fourthLayer.bounds = CGRectMake(0, 0, 30, 30);
        fourthLayer.cornerRadius = 15;
        fourthLayer.position = CGPointMake(fourthView.bounds.size.width/2, fourthView.bounds.size.height/2);
    
        CABasicAnimation * fourthViewScaleAnimation;
        fourthViewScaleAnimation = [CABasicAnimation animation];
        fourthViewScaleAnimation.keyPath = @"transform.scale";
        fourthViewScaleAnimation.fromValue = @1;
        fourthViewScaleAnimation.toValue = @2;
        fourthViewScaleAnimation.duration = 1.5;
        fourthViewScaleAnimation.repeatCount = HUGE_VALF;
        fourthViewScaleAnimation.autoreverses = YES;
    
        [fourthView.layer addAnimation:fourthViewScaleAnimation forKey:@"fourthViewAnimation"];
    
        [self.view addSubview:fourthView];
    

    由于无法更改UIView的来源,我需要找到一种方法来执行以下任一操作:

    1. 始终更新子图层的位置以补偿变化的原点。
    2. 使第四个示例中的子图层大小不会随着UIView的缩放而改变。
    3. 我不能做多个UIViews,因为我打算将整个图层添加到MKAnnotationView。

      谢谢!

1 个答案:

答案 0 :(得分:0)

我想出了一个解决方案,我感到愚蠢,我没有立刻想到它。我可以使用两层。 UIView不会改变大小。一层扩展和收缩,并且由于UIView没有移动,它上面的另一层保持在相同的位置。