Позиционирование подслоя в центре анимированного UIView
У меня есть UIView в форме круга, который расширяется и сжимается. Мне нужно иметь подслой, расположенный в его центре, который остается того же размера, что и анимация. Приведенный ниже код содержит четыре примера, показывающих, что я пробовал. Его можно скопировать и вставить как есть.
- Первый UIView не анимирован. Его подслой расположен в его центре, но он должен быть расположен относительно происхождения UIView. Это проблема, когда границы и происхождение UIView изменяются во время анимации.
- Второй UIView имеет две анимации: одну для
@"bounds"
и один для@"cornerRadius"
, Это расположение приводит к тому, что подслой заканчивается в начале экрана (вверху слева). - Третий UIView также имеет две анимации: на этот раз для
@"bounds.size"
а также@"cornerRadius"
, Подслой остается того же размера, что хорошо, но он не остается в центре UIView. Я пытался использовать[thirdView.layer setNeedsDisplayOnBoundsChange:YES];
чтобы компенсировать изменение границ, но это не сработало. Я тоже пробовалthirdView.contentMode = UIViewContentModeRedraw;
, - Четвертый 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 невозможно, мне нужно найти способ сделать одну из следующих вещей:
- Последовательно обновляйте положение подслоя, чтобы компенсировать изменение источника.
- Сделайте так, чтобы размер подслоя в четвертом примере не изменялся при масштабировании UIView.
Я не могу сделать несколько UIViews, потому что я намерен добавить весь слой в MKAnnotationView.
Спасибо!
1 ответ
Я нашел решение и чувствую себя глупо, что не сразу об этом подумал. Я могу использовать два слоя. UIView не меняет размер. Один слой расширяется и сжимается, а другой слой поверх него остается в том же положении, поскольку UIView не перемещается.