gpt4 book ai didi

ios - 使用自动布局时,如何调整 CALayer 的 anchor ?

转载 作者:IT王子 更新时间:2023-10-29 07:26:41 27 4
gpt4 key购买 nike

备注 :自从提出这个问题以来,事情已经发生了变化;见 here以获得良好的近期概览。

在自动布局之前,您可以通过存储框架、设置 anchor 和恢复框架来更改 View 图层的 anchor ,而无需移动 View 。

在自动布局的世界中,我们不再设置框架,但约束似乎无法将 View 的位置调整回我们想要的位置。你可以破解约束来重新定位你的 View ,但是在旋转或其他调整大小的事件中,这些再次变得无效。

以下好主意不起作用,因为它创建了“无效的布局属性配对(左和宽度)”:

layerView.layer.anchorPoint = CGPointMake(1.0, 0.5);
// Some other size-related constraints here which all work fine...
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:layerView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:layerView
attribute:NSLayoutAttributeWidth
multiplier:0.5
constant:20.0]];

我的目的是设置 layerView 的左边缘,带有调整后的 anchor 的 View ,为其宽度的一半加上 20(我想要从 super View 的左边缘插入的距离)。

在使用自动布局布局的 View 中,是否可以在不更改 View 位置的情况下更改 anchor ?我是否需要使用硬编码值并在每次旋转时编辑约束?我希望不会。

我需要更改 anchor ,以便在对 View 应用变换时获得正确的视觉效果。

最佳答案

[编辑:警告:整个随后的讨论可能会过时或至少被 iOS 8 严重缓解,它可能不再犯在应用 View 转换时触发布局的错误。]

自动布局与 View 变换

自动布局在 View 转换中完全不能发挥作用。据我所知,原因是您不应该弄乱具有转换(默认标识转换除外)的 View 的框架 - 但这正是自动布局所做的。自动布局的工作方式是在 layoutSubviews 中运行时会冲破所有约束并相应地设置所有 View 的框架。

换句话说,约束不是魔术;它们只是一个待办事项 list 。 layoutSubviews是待办事项列表完成的地方。它通过设置框架来实现。

我不禁认为这是一个错误。如果我将此转换应用于 View :

v.transform = CGAffineTransformMakeScale(0.5,0.5);

我希望看到 View 的中心与以前相同,并且尺寸只有一半。但根据它的限制,这可能根本不是我所看到的。

[实际上,这里还有第二个惊喜:对 View 应用变换会立即触发布局。这在我看来是另一个错误。或者它可能是第一个错误的核心。我期望的是能够至少在布局时间之前进行转换,例如设备被旋转 - 就像我可以在布局时间之前摆脱帧动画一样。但实际上布局时间是即时的,这似乎是错误的。]

解决方案 1:没有约束

当前的一个解决方案是,如果我要对 View 应用半永久变换(而不仅仅是以某种方式暂时摆动它),则删除所有影响它的约束。不幸的是,这通常会导致 View 从屏幕上消失,因为自动布局仍然发生,现在没有限制告诉我们把 View 放在哪里。所以除了去除约束之外,我还设置了 View 的 translatesAutoresizingMaskIntoConstraints是。该 View 现在以旧方式工作,有效地不受自动布局的影响。 (显然,它受自动布局的影响,但隐式自动调整大小掩码约束导致其行为就像在自动布局之前一样。)

解决方案 2:仅使用适当的约束

如果这看起来有点激烈,另一种解决方案是设置约束以与预期的转换正常工作。例如,如果一个 View 的大小完全由其内部固定的宽度和高度确定,并且完全由其中心定位,那么我的缩放变换将按我的预期工作。在此代码中,我删除了 subview ( otherView ) 上的现有约束,并将它们替换为这四个约束,为其赋予固定的宽度和高度,并仅将其固定在其中心。之后,我的比例转换工作:
NSMutableArray* cons = [NSMutableArray array];
for (NSLayoutConstraint* con in self.view.constraints)
if (con.firstItem == self.otherView || con.secondItem == self.otherView)
[cons addObject:con];

[self.view removeConstraints:cons];
[self.otherView removeConstraints:self.otherView.constraints];
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeCenterX relatedBy:0 toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:self.otherView.center.x]];
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:self.otherView.center.y]];
[self.otherView addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeWidth relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:self.otherView.bounds.size.width]];
[self.otherView addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeHeight relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:self.otherView.bounds.size.height]];

结果是,如果您没有影响 View 框架的约束,自动布局将不会触及 View 的框架——这正是涉及转换时您所追求的。

解决方案 3:使用 subview

上述两种解决方案的问题在于,我们失去了定位 View 的约束的好处。所以这是解决这个问题的解决方案。从一个不可见的 View 开始,它的工作只是作为一个宿主,并使用约束来定位它。在里面,将真实 View 作为 subview 。使用约束在宿主 View 中定位 subview ,但将这些约束限制为在我们应用转换时不会反击的约束。

这是一个插图:

enter image description here

白色 View 为主机 View ;你应该假装它是透明的,因此是不可见的。红色 View 是它的 subview ,通过将其中心固定到宿主 View 的中心来定位。现在我们可以毫无问题地围绕其中心缩放和旋转红色 View ,事实上,插图表明我们已经这样做了:
self.otherView.transform = CGAffineTransformScale(self.otherView.transform, 0.5, 0.5);
self.otherView.transform = CGAffineTransformRotate(self.otherView.transform, M_PI/8.0);

同时,当我们旋转设备时,主机 View 上的约束将其保持在正确的位置。

解决方案 4:改用层变换

使用图层变换代替 View 变换,它不会触发布局,因此不会立即与约束发生冲突。

例如,这个简单的“throb” View 动画可能会在自动布局下中断:
[UIView animateWithDuration:0.3 delay:0
options:UIViewAnimationOptionAutoreverse
animations:^{
v.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
v.transform = CGAffineTransformIdentity;
}];

尽管最终 View 的大小没有变化,只是设置了它的 transform导致布局发生,约束可以使 View 跳跃。 (这感觉像是一个错误还是什么?)但是如果我们对 Core Animation 做同样的事情(使用 CABasicAnimation 并将动画应用到 View 层),布局不会发生,并且它工作正常:
CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"];
ba.autoreverses = YES;
ba.duration = 0.3;
ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
[v.layer addAnimation:ba forKey:nil];

关于ios - 使用自动布局时,如何调整 CALayer 的 anchor ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12943107/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com