Autolayout控制在运行时的ACTUAL位置?

时间:2014-10-07 17:38:15

标签: ios objective-c autolayout nsautolayout

使用XCode 6.0.1,iOS 8。

我有一个通过Autolayout / constraints放置的UIButton。

我正在尝试以编程方式添加相对于第一个按钮定位的按钮。具体来说,我将它们围绕初始按钮的中心点围成一圈。我用来查找新按钮坐标的数学工作正常,但是:

autolayout&#d; d按钮报告它相对于536x536 superview界面构建器正在使用的原点,而不是设备的实际屏幕大小。

我知道这是因为约束说"容器中的X和Y中心"并且它确实出现在屏幕的中间,但无论设备/屏幕大小如何,frame.origin =(268,268),这是IB中视图的中心(536/2 = 268)。

那么有没有办法以某种方式将其转换为"实际的设备坐标"而不是原始界面构建器坐标?

TIA

编辑:我需要翻译它,无论它是否居中。我意识到我可以获得设备的屏幕尺寸,如果它居中,则除以2。

Edit2:@jrturton - 它在运行时报告其位置在哪里?什么财产?原点和中心都是正确的。无论如何,代码:

创建按钮:

- (void)setupButtons: (int)buttonCount
{
if ((buttonCount > MAX_BUTTONS) || (buttonCount < MIN_BUTTONS)) {
    return;
}

float totalRads = degreesToRadians(360.0);
float deltaRads = totalRads / (float)buttonCount;
float radius = 30.0f;

NSMutableArray *buttons = [[NSMutableArray alloc] init];
CGRect centerFrame = self.centerMenuButton.frame;
for (int i = 0; i < buttonCount; i++) {

    CGPoint dest = CGPointMake(
                               (radius * cosf(i * deltaRads) + centerFrame.origin.x),
                               (radius * sinf(i * deltaRads) + centerFrame.origin.y)
                               );

    CGRect frame = CGRectMake(dest.x, dest.y, 64.0, 64.0);
    UIButton *button = [[UIButton alloc] initWithFrame:frame];
    [button setImage:[UIImage imageNamed:@"pink_star"] forState:UIControlStateNormal];
    [buttons addObject:button];
}

_menuButtons = [[NSArray alloc] initWithArray:buttons];
}

并显示它们:

- (void)showMenu
{
NSLog(@"showMenu");

for (int i = 0; i < [_menuButtons count]; i++) {
    UIButton *btn = [_menuButtons objectAtIndex:i];
    NSLog(@"origin: %f, %f", btn.frame.origin.x, btn.frame.origin.y);
    [self.view addSubview:btn];
}

_menuOpen = YES;
}

我有一些NSLog用于原始自动布局按钮的中心(约束在IB中设置):

RadialMenuText[14125:6281339] x: 268.000000, y: 268.000000

每个按钮一个(当前为2个):

RadialMenuText[14125:6281339] origin: 298.000000, 268.000000
RadialMenuText[14125:6281339] origin: 238.000000, 267.999997

除了舍入误差之外,数学看起来是半正确的,因为X坐标每次都以正确的方向移动半径。但同样 - 起始坐标不正确,因为自动布局&#d; d按钮正在报告(268,268)。

2 个答案:

答案 0 :(得分:1)

我猜您是从setupButtons:致电viewDidLoad。在视图控制器从故事板加载其视图之后,但在系统调整当前设备和方向的视图(及其子视图)之前,会发生这种情况。

我建议您通过使用约束来定位按钮而不是设置框架来解决此问题。

除非两个视图位于同一视图层次结构中,否则两个视图之间不能有约束。因此,将按钮添加到setupButtons:中的视图层次结构中,但将它们设置为隐藏。在showMenu中,让它们可见。

- (void)setupButtons:(int)buttonCount {
    if (buttonCount > MAX_BUTTONS |buttonCount < MIN_BUTTONS) {
        return;
    }

    float totalRads = degreesToRadians(360.0);
    float deltaRads = totalRads / (float)buttonCount;
    float radius = 30.0f;

    NSMutableArray *buttons = [[NSMutableArray alloc] init];
    UIView *centerView = self.centerMenuButton;
    for (int i = 0; i < buttonCount; i++) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.translatesAutoresizingMaskIntoConstraints = NO;
        [button setImage:[UIImage imageNamed:@"pink_star"] forState:UIControlStateNormal];
        button.hidden = YES;
        [self.view addSubview:button];
        [buttons addObject:button];

        [button addConstraint:[NSLayoutConstraint
            constraintWithItem:button attribute:NSLayoutAttributeWidth
            relatedBy:NSLayoutRelationEqual
            toItem:nil attribute:NSLayoutAttributeNotAnAttribute
            multiplier:0 constant:64]];
        [button addConstraint:[NSLayoutConstraint
            constraintWithItem:button attribute:NSLayoutAttributeHeight
            relatedBy:NSLayoutRelationEqual
            toItem:nil attribute:NSLayoutAttributeNotAnAttribute
            multiplier:0 constant:64]];

        CGFloat radians = i * 2 * M_PI / buttonCount;
        [self.view addConstraint:[NSLayoutConstraint
            constraintWithItem:button attribute:NSLayoutAttributeCenterX
            relatedBy:NSLayoutRelationEqual
            toItem:centerView attribute:NSLayoutAttributeCenterX
            multiplier:1 constant:radius * cos(radians)]];
        [self.view addConstraint:[NSLayoutConstraint
            constraintWithItem:button attribute:NSLayoutAttributeCenterY
            relatedBy:NSLayoutRelationEqual
            toItem:centerView attribute:NSLayoutAttributeCenterY
            multiplier:1 constant:radius * sin(radians)]];
    }

    _menuButtons = [buttons copy];
}

- (void)showMenu {
    NSLog(@"showMenu");

    for (int i = 0; i < _menuButtons.count; i++) {
        UIButton *btn = _menuButtons[i];
        NSLog(@"origin: %f, %f", btn.frame.origin.x, btn.frame.origin.y);
        btn.hidden = NO;
    }

    _menuOpen = YES;
}

答案 1 :(得分:-1)

NSLayoutConstraints在layoutSubviews之后处理。如果您从自动布局视图中删除NSLayoutConstraints并替换为UIViewAutoresizingFlexible*常量,则当您在[super layoutSubviews]覆盖中调用layoutSubviews时,您的按钮框架将会更新。

@jrturton对于你的中心计算也提出了一个很好的观点。如果您的投诉是被报告的中心是其超级视图中的中心,那么这是预期的行为。如果您希望中心相对于屏幕,则需要使用[[UIScreen mainScreen] convertPoint:point fromView:theView]转换它。