使用自动版式时,如何调整CALayer的锚点?


161

注意:自从提出此问题以来,事情一直在发展;请参阅此处以获得近期的良好概述。


在自动布局之前,可以通过存储框架,设置锚点并还原框架来更改视图图层的锚点,而无需移动视图。

在自动布局的世界中,我们不再设置框架,但是约束似乎并没有完成将视图的位置调整回我们想要的位置的任务。您可以修改约束以重新定位视图,但是在旋转或其他大小调整事件上,这些约束将再次变为无效。

以下聪明的想法行不通,因为它会创建“布局属性(左和宽度)无效配对”:

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具有调整后的锚点的视图的左边缘设置为其宽度的一半加上20(我要从超级视图的左边缘插入的距离)。

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

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


考虑到这里的所有内容,即使您已使上面的代码正常工作,也似乎最终还是会导致模棱两可的布局。怎么layerView知道它的宽度?它是否将其右边粘在其他东西上?
John Estropia 2012年

覆盖了//Size-related constraints that work fine-图层视图的宽度和高度是从超级视图派生的。
jrturton 2012年

Answers:


361

[编辑:警告:整个随后的讨论可能会被iOS 8过时,或者至少在很大程度上得到缓解,iOS 8可能不再会导致在应用视图转换时触发布局的错误。

自动布局与视图转换

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

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

我不禁将此视为错误。如果我将此转换应用于视图:

v.transform = CGAffineTransformMakeScale(0.5,0.5);

我希望看到该视图的中心在与以前相同的位置,并且只有其一半大小。但是根据它的约束,可能根本不是我所看到的。

[实际上,这里还有第二个惊喜:将变换应用于视图会立即触发布局。在我看来,这是另一个错误。也许这是第一个错误的核心。我期望的是至少在布局时间之前能够避免变形,例如旋转设备-就像我可以在布局时间之前避免使用帧动画一样。但是实际上布局时间是即时的,这似乎是错误的。]

解决方案1:无约束

当前的一种解决方案是,如果我要对视图应用半永久性转换(而不仅仅是以某种方式临时摆动),以消除影响它的所有约束。不幸的是,这通常会导致视图从屏幕上消失,因为仍然会进行自动布局,并且现在没有约束告诉我们将视图放置在何处。因此,除了消除约束之外,我还将视图设置translatesAutoresizingMaskIntoConstraints为“是”。现在,该视图以旧的方式工作,实际上不受自动布局的影响。(这由自动布局的影响,很明显,但隐含的自动尺寸面具限制导致其行为是就像它是自动布局之前。)

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

如果这看起来有些过激,则另一种解决方案是将约束设置为与预期的转换一起正常工作。例如,如果一个视图仅由其内部固定宽度和高度确定大小,并仅由其中心定位,则我的缩放变换将按预期工作。在这段代码中,我删除了子视图(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]];

结果是,如果您没有影响视图框架的约束,则自动布局不会碰到视图框架-这就是您进行变换后所要执行的操作。

解决方案3:使用子视图

上述两种解决方案的问题在于,我们失去了约束来定位我们的观点的好处。因此,这里有一个解决方案。从一个不可见的视图开始,其工作仅是充当宿主,然后使用约束对其进行定位。在其中,将真实视图作为子视图。使用约束将子视图放置在宿主视图中,但将这些约束限制为在应用转换时不会反击的约束。

这是一个例子:

在此处输入图片说明

白色视图是主机视图;您应该假装它是透明的,因此是不可见的。红色视图是其子视图,通过将其中心固定到宿主视图的中心来定位。现在,我们可以毫无问题地缩放和旋转红色视图,并且该插图确实表明我们已经这样做了:

self.otherView.transform = CGAffineTransformScale(self.otherView.transform, 0.5, 0.5);
self.otherView.transform = CGAffineTransformRotate(self.otherView.transform, M_PI/8.0);

同时,当我们旋转设备时,对宿主视图的约束将其保持在正确的位置。

解决方案4:改为使用层变换

代替视图变换,请使用图层变换,该变换不会触发布局,因此不会引起与约束的立即冲突。

例如,这个简单的“跳动”视图动画很可能会在自动布局下中断:

[UIView animateWithDuration:0.3 delay:0
                    options:UIViewAnimationOptionAutoreverse
                 animations:^{
    v.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
    v.transform = CGAffineTransformIdentity;
}];

即使最后视图的大小没有变化,仅设置其transform原因布局就可以发生,而约束条件可以使视图跳动。(这听起来像是个错误还是什么?)但是,如果我们对Core Animation做同样的事情(使用CABasicAnimation并将动画应用于视图的图层),则不会发生布局,并且可以正常工作:

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];

3
转换不是引起我问题的原因,只是设置了新的锚点。我将尽力消除约束并尝试使用自动调整大小的蒙版。
jrturton

1
我在这里听不懂。解决方案4:当将变换也应用到也会影响自动布局的衬层时,因为视图的transform属性是指衬层的变换
Luca Bartoletti 2014年

1
@Andy相反,在iOS 8上,问题已完全消失,我的全部答案都是不必要的
matt

1
@Sunkas我回答了您的问题。
Ben Sinclair 2014年

2
在iOS 8层也变换触发自动布局
CarmeloS

41

我有一个类似的Isuue,只是从Apple的Autolayout团队那里听到了回音。他们建议使用容器视图方法,但建议创建一个UIView的子类来覆盖layoutSubviews并在其中应用自定义布局代码-就像一个魅力

头文件看起来像这样,以便您可以直接从Interface Builder链接选择的子视图

#import <UIKit/UIKit.h>

@interface BugFixContainerView : UIView
@property(nonatomic,strong) IBOutlet UIImageView *knobImageView;
@end

并且m文件应用如下特殊代码:

#import "BugFixContainerView.h"

@implementation BugFixContainerView
- (void)layoutSubviews
{
    static CGPoint fixCenter = {0};
    [super layoutSubviews];
    if (CGPointEqualToPoint(fixCenter, CGPointZero)) {
        fixCenter = [self.knobImageView center];
    } else {
        self.knobImageView.center = fixCenter;
    }
}
@end

如您所见,它在首次调用时会抓住View的中心点,并在以后的调用中重用该Position以相应地放置View。从这种意义上讲,它会覆盖[自动布局代码],该代码发生在[super layoutSubviews]之后;其中包含自动布局代码。

这样,就不再需要避免自动布局,但是当默认行为不再适用时,您可以创建自己的自动布局。当然,您可以应用比该示例更复杂的内容,但这只是我所需要的,因为我的应用只能使用人像模式。


5
感谢您发布此信息。自从我写出答案以来,我肯定已经了解了覆盖的价值layoutSubviews。不过,我要补充一点,这里的Apple只是让做我一直认为他们应该做的事情(在执行Autolayout的过程中)。
马特2013年

您是对的,但我想这与问题本身并没有真正的关系。由于他们提供了上述代码,我对此感到满意!
2013年

4
自动布局团队自己建议创建一个自定义容器子类只是为了解决自动布局如何破坏视图系统中长期存在的直观行为,这是令人悲伤和荒谬的。

8

我找到一种简单的方法。它适用于iOS 8和iOS 9。

当您使用基于框架的布局时,就像调整anchorPoint一样:

let oldFrame = layerView.frame
layerView.layer.anchorPoint = newAnchorPoint
layerView.frame = oldFrame

当您使用自动布局调整视图的锚点时,您将执行相同的操作,但约束方式相同。当anchorPoint从(0.5,0.5)更改为(1,0.5)时,layerView将向左移动一半视图宽度的长度,因此您需要对此进行补偿。

我不理解问题中的约束,因此,假设您使用一个常量相对于superView centerX添加了centerX约束:layerView.centerX = superView.centerX +常量

layerView.layer.anchorPoint = CGPoint(1, 0.5)
let centerXConstraint = .....
centerXConstraint.constant = centerXConstraint.constant + layerView.bounds.size.width/2

我的朋友为您杯最好的啤酒。这是这么好解决方法:d
Błażej

3

如果您使用的是自动布局,那么从长远来看,我看不到如何手动设置位置,因为最终自动布局会掩盖您在计算自己的布局时设置的位置值。

而是需要自己修改布局约束,以补偿通过设置anchorPoint产生的更改。以下功能针对未转换的视图执行此操作。

/**
  Set the anchorPoint of view without changing is perceived position.

 @param view view whose anchorPoint we will mutate
 @param anchorPoint new anchorPoint of the view in unit coords (e.g., {0.5,1.0})
 @param xConstraint an NSLayoutConstraint whose constant property adjust's view x.center
 @param yConstraint an NSLayoutConstraint whose constant property adjust's view y.center

  As multiple constraints can contribute to determining a view's center, the user of this
 function must specify which constraint they want modified in order to compensate for the
 modification in anchorPoint
 */
void SetViewAnchorPointMotionlesslyUpdatingConstraints(UIView * view,CGPoint anchorPoint,
                                                       NSLayoutConstraint * xConstraint,
                                                       NSLayoutConstraint * yConstraint)
{
  // assert: old and new anchorPoint are in view's unit coords
  CGPoint const oldAnchorPoint = view.layer.anchorPoint;
  CGPoint const newAnchorPoint = anchorPoint;

  // Calculate anchorPoints in view's absolute coords
  CGPoint const oldPoint = CGPointMake(view.bounds.size.width * oldAnchorPoint.x,
                                 view.bounds.size.height * oldAnchorPoint.y);
  CGPoint const newPoint = CGPointMake(view.bounds.size.width * newAnchorPoint.x,
                                 view.bounds.size.height * newAnchorPoint.y);

  // Calculate the delta between the anchorPoints
  CGPoint const delta = CGPointMake(newPoint.x-oldPoint.x, newPoint.y-oldPoint.y);

  // get the x & y constraints constants which were contributing to the current
  // view's position, and whose constant properties we will tweak to adjust its position
  CGFloat const oldXConstraintConstant = xConstraint.constant;
  CGFloat const oldYConstraintConstant = yConstraint.constant;

  // calculate new values for the x & y constraints, from the delta in anchorPoint
  // when autolayout recalculates the layout from the modified constraints,
  // it will set a new view.center that compensates for the affect of the anchorPoint
  CGFloat const newXConstraintConstant = oldXConstraintConstant + delta.x;
  CGFloat const newYConstraintConstant = oldYConstraintConstant + delta.y;

  view.layer.anchorPoint = newAnchorPoint;
  xConstraint.constant = newXConstraintConstant;
  yConstraint.constant = newYConstraintConstant;
  [view setNeedsLayout];
}

我承认这可能不是您想要的所有东西,因为通常您想要修改anchorPoint的唯一原因是设置一个转换。这将需要一个更复杂的函数来更新布局约束,以反映可能由transform属性本身引起的所有帧更改。这很棘手,因为变换会对框架产生很大影响。缩放或旋转变换会使框架更大,因此我们需要更新任何宽度或高度限制等。

如果您仅将转换用于临时动画,那么上面的内容就足够了,因为我不相信自动布局会阻止飞行中的动画呈现代表纯粹瞬时违反约束的图像。


不幸的是,我正在使用转换。设置位置很好,因为每次布局视图时都会调用此方法,因此不会造成麻烦。我在考虑重写layoutRect可能是一个更好的解决方案(在您以前的回答之一中提到),但是我还没有尝试过。
jrturton 2012年

顺便说一下,这是我一直在使用的测试台。如果有人弄清楚了,那就太好了:github.com/algal/AutolayoutAnchorPointTestRig
algal

这应该是公认的答案。@matt的答案甚至与锚点无关。
Iulian Onofrei

3

tl:dr:您可以为约束之一创建出口,以便可以将其删除并重新添加回去。


我创建了一个新项目,并在中心添加了一个固定大小的视图。约束如下图所示。

我能想到的最小示例的约束。

接下来,我为要旋转的视图和中心x对齐约束添加了一个出口。

@property (weak, nonatomic) IBOutlet UIView *rotatingView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *xAlignmentContstraint;

稍后viewDidAppear我计算新的锚点

UIView *view = self.rotatingView;

CGPoint rotationPoint = // The point I'm rotating around... (only X differs)
CGPoint anchorPoint = CGPointMake((rotationPoint.x-CGRectGetMinX(view.frame))/CGRectGetWidth(view.frame),
                                  (rotationPoint.y-CGRectGetMinY(view.frame))/CGRectGetHeight(view.bounds));

CGFloat xCenterDifference = rotationPoint.x-CGRectGetMidX(view.frame);

view.layer.anchorPoint = anchorPoint;

然后,删除我有出口的约束,创建一个新的偏移量,然后再次添加回去。之后,我告诉更改了约束的视图它需要更新约束。

[self.view removeConstraint:self.xAlignmentContstraint];
self.xAlignmentContstraint = [NSLayoutConstraint constraintWithItem:self.rotatingView
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1.0
                                                           constant:xDiff];
[self.view addConstraint:self.xAlignmentContstraint];
[self.view needsUpdateConstraints];

最后,我只是将旋转动画添加到旋转视图中。

CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotate.toValue = @(-M_PI_2);
rotate.autoreverses = YES;
rotate.repeatCount = INFINITY;
rotate.duration = 1.0;
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

[view.layer addAnimation:rotate forKey:@"myRotationAnimation"];

即使旋转设备或以其他方式导致旋转约束,旋转的图层看起来仍保持居中(应保持居中)。新的约束和更改的锚点在视觉上相互抵消。


1
这将适合我的特定情况,看起来不可能有一个很好的通用解决方案。
jrturton 2013年

1

我当前的解决方案是在中手动调整图层的位置viewDidLayoutSubviews。该代码也可以用于layoutSubviews视图子类,但是在我的情况下,我的视图是视图控制器内部的顶级视图,因此这意味着我不必创建UIView子类。

似乎太费力了,所以其他答案很受欢迎。

-(void)viewDidLayoutSubviews
{
    for (UIView *view in self.view.subviews)
    {
        CGPoint anchorPoint = view.layer.anchorPoint;
        // We're only interested in views with a non-standard anchor point
        if (!CGPointEqualToPoint(CGPointMake(0.5, 0.5),anchorPoint))
        {
            CGFloat xDifference = anchorPoint.x - 0.5;
            CGFloat yDifference = anchorPoint.y - 0.5;
            CGPoint currentPosition = view.layer.position;

            // Use transforms if we can, otherwise manually calculate the frame change
            // Assuming a transform is in use since we are changing the anchor point. 
            if (CATransform3DIsAffine(view.layer.transform))
            {
                CGAffineTransform current = CATransform3DGetAffineTransform(view.layer.transform);
                CGAffineTransform invert = CGAffineTransformInvert(current);
                currentPosition = CGPointApplyAffineTransform(currentPosition, invert);
                currentPosition.x += (view.bounds.size.width * xDifference);
                currentPosition.y += (view.bounds.size.height * yDifference);
                currentPosition = CGPointApplyAffineTransform(currentPosition, current);
            }
            else
            {
                CGFloat transformXRatio = view.bounds.size.width / view.frame.size.width;

                if (xDifference < 0)
                    transformXRatio = 1.0/transformXRatio;

                CGFloat transformYRatio = view.bounds.size.height / view.frame.size.height;
                if (yDifference < 0)
                    transformYRatio = 1.0/transformYRatio;

                currentPosition.x += (view.bounds.size.width * xDifference) * transformXRatio;
                currentPosition.y += (view.bounds.size.height * yDifference) * transformYRatio;
            }
            view.layer.position = currentPosition;
        }

    }
}

1

激发了马特的回答,我决定尝试另一种方法。可以使用具有适当应用约束的容器视图。然后,可以使用自动调整大小蒙版和显式框架设置将具有修改后的锚点的视图放置在容器视图内,就像在过去的糟糕时期一样。

无论如何,对我来说,这是一种享受。视图是在viewDidLoad中设置的:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UIView *redView = [UIView new];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[redView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(redView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[redView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(redView)]];
    self.redView = redView;

    UIView *greenView = [UIView new];
    greenView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    greenView.layer.anchorPoint = CGPointMake(1.0, 0.5);
    greenView.frame = redView.bounds;
    greenView.backgroundColor = [UIColor greenColor];
    [redView addSubview:greenView];
    self.greenView = greenView;

    CATransform3D perspective = CATransform3DIdentity;
    perspective.m34 = 0.005;
    self.redView.layer.sublayerTransform = perspective;
}

由于绿色视图上的自动调整蒙版,此时红色视图的帧为零并不重要。

我在动作方法上添加了旋转变换,结果如下:

在此处输入图片说明

它似乎在设备旋转期间迷失了自己,因此我将其添加到了viewDidLayoutSubviews方法中:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    CATransform3D transform = self.greenView.layer.transform;
    self.greenView.layer.transform = CATransform3DIdentity;
    self.greenView.frame = self.redView.bounds;
    self.greenView.layer.transform = transform;
    [CATransaction commit];

}

我想知道在您的情况下,view.layer独自呆在子层中进行所有工作是否会更加容易view.layer。换句话说,视图将只是一个宿主,而所有的图形和子层变换等都将向下扩展,不受约束的影响。
马特2013年

1
好的,受子视图解决方案的启发,我已将其添加到我的文章中!感谢您让我在您的沙箱中玩耍……
马特2013年

0

我认为您正在用这种方法来实现自动布局的目的。您确实提到宽度和右边缘取决于超级视图,那么为什么不仅仅沿着这种思路添加约束呢?

失去anchorPoint / transform范例,然后尝试:

[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:layerView
                             attribute:NSLayoutAttributeRight
                             relatedBy:NSLayoutRelationEqual 
                                toItem:self.view 
                             attribute:NSLayoutAttributeWidth 
                            multiplier:1.0f
                              constant:-somePadding]];
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:layerView
                             attribute:NSLayoutAttributeWidth
                             relatedBy:NSLayoutRelationEqual 
                                toItem:someViewWeDependTheWidthOn
                             attribute:NSLayoutAttributeWidth 
                            multiplier:0.5f // because you want it to be half of someViewWeDependTheWidthOn
                              constant:-20.0f]]; // your 20pt offset from the left

NSLayoutAttributeRight约束装置完全一样anchorPoint = CGPointMake(1.0, 0.5),和NSLayoutAttributeWidth约束大致相当于以前的代码的NSLayoutAttributeLeft


感谢您的回答,但我不能“丢掉锚点/变换范例”。我需要应用变换,并调整锚点以进行正确的变换。
jrturton 2012年

为了进一步说明,在这种特定情况下,有时需要通过沿其最右边缘的Y轴旋转将变换后的视图折叠到屏幕中。因此,锚点必须被移动。我也在寻找一个通用的解决方案。
jrturton 2012年

当然,您仍然可以保留anchorPoint,我的意思是您不应该将其用于测量。UIView自动布局系统应独立于CALayer转换。因此,UIView:layout,CALayer:appearance / animations
John Estropia 2012年

1
应该,但不是。您实际尝试过吗?自动布局完成后,更改锚点会偏移图层的位置。您的解决方案不适用于修改的锚点。
jrturton 2012年

是的,我可以对具有约束的视图使用不同的anchorPoints。您的回答viewDidLayoutSubviews应该可以解决该问题;position总是和anchorPoint。我的回答仅显示了如何定义身份转换的约束。
约翰·埃斯特罗皮亚

0

这个问题和答案激发了我解决自动布局和缩放但具有滚动视图的问题。我在github上创建了我的解决方案的示例:

https://github.com/hansdesmedt/AutoLayout-scrollview-scale

这是一个UIScrollView的示例,其中的自定义分页完全在AutoLayout中完成,并且可以通过长按并点按以缩放来缩放(CATransform3DMakeScale)。与iOS 6和7兼容。


0

这是一个很大的话题,我还没有阅读所有评论,但是遇到了同样的问题。

我从XIB看到了带有自动布局的视图。我想更新其transform属性。将视图嵌入到容器视图中并不能解决我的问题,因为自动布局对容器视图的作用很奇怪。这就是为什么我刚刚添加了第二个容器视图以包含包含我的视图并对其进行转换的容器视图。


0

tl; dr假设您将锚点更改为(0,0)。锚点现在位于左上方。每当您在自动布局中看到单词center时,都应该想到top-left

调整anchorPoint时,只需更改AutoLayout的语义。自动布局不会干扰您的anchorPoint,反之亦然。如果您不理解这一点,那将是一段糟糕的时光


例:

图A. 没有锚点修改

#Before changing anchor point to top-left
view.size == superview.size
view.center == superview.center

图B. 锚点更改为左上方

view.layer.anchorPoint = CGPointMake(0, 0)
view.size == superview.size
view.center == superview.topLeft                <----- L0-0K, center is now top-left

图A和图B看起来完全一样。没有改变。只是中心所指的定义已更改。


一切都很好,但是并没有回答您的约束与中心无关时该怎么做的问题。
jrturton
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.