在动画 UIView 的中心定位子层
Posted
技术标签:
【中文标题】在动画 UIView 的中心定位子层【英文标题】:Positioning sublayer on center of animated UIView 【发布时间】:2015-04-04 00:12:01 【问题描述】:我有一个形状像一个可以扩展和收缩的圆圈的 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 的缩放而改变。
我不能做多个 UIView,因为我打算将整个层添加到 MKAnnotationView。
谢谢!
【问题讨论】:
【参考方案1】:我想出了一个解决方案,但我觉得自己很愚蠢,因为我没有立即想到它。我可以使用两层。 UIView 不会改变大小。由于 UIView 没有移动,一层扩展和收缩,而其顶部的另一层保持在同一位置。
【讨论】:
是的。那将是我的建议。你应该接受你的答案,这样其他人就可以知道它已经回答了。以上是关于在动画 UIView 的中心定位子层的主要内容,如果未能解决你的问题,请参考以下文章
Python selenium —— 父子兄弟相邻节点定位方式详解
Appium Inspector 无法在 iOS Element Hierarchy 中定位子元素