Позиционирование подслоя в центре анимированного UIView

У меня есть 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, как я хочу, но он не остается того же размера. Мне нужно, чтобы размер подслоя был независимым, потому что я намереваюсь его оживить.

Вот весь код. Это выглядит много, но это довольно простые вещи.

    - (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.

Я не могу сделать несколько UIViews, потому что я намерен добавить весь слой в MKAnnotationView.

Спасибо!

1 ответ

Решение

Я нашел решение и чувствую себя глупо, что не сразу об этом подумал. Я могу использовать два слоя. UIView не меняет размер. Один слой расширяется и сжимается, а другой слой поверх него остается в том же положении, поскольку UIView не перемещается.

Другие вопросы по тегам