2014-10-07 3 views
0

XCode 6.0.1, iOS 8 사용런타임시 Autolayout'd 컨트롤의 ACTUAL 위치가 맞습니까?

나는 Autolayout/constraints를 통해 배치 한 UIButton이 있습니다.

첫 번째 단추에 상대적으로 배치 된 단추를 프로그래밍 방식으로 추가하려고합니다. 특히 초기 버튼의 중심점을 중심으로 원에 추가하고 있습니다.

autolayout'd 버튼이 장치의 실제 화면 크기가 아닌 536x536 수퍼 뷰 인터페이스 빌더와 관련하여 원점을보고하고 있다는 것을 제외하고는 새 버튼의 좌표를 찾기 위해 사용하고 있습니다. .

제약 조건이 "컨테이너의 가운데 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; 
} 

내가 (IB에서 설정 한 제약 조건) 원래, 자동 레이아웃 버튼의 중심에 대한 몇 가지 NSLogs이 :

각 버튼 당 하나 (현재 2 개) :

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

반올림 오류 이외에도 X 좌표가 매번 올바른 방향으로 반경에 따라 이동한다는 점에서 반올림 오류가 발생하지 않습니다. 그러나 다시 - autolayout'd 버튼이보고 중이기 때문에 시작 좌표가 올바르지 않습니다 (268, 268).

+0

Xcode 6에 내장 된 뷰 디버깅을 사용해보십시오. 그렇게하면 버튼 위치와 런타임 제약 조건 및 위치가 표시됩니다. 다음은 Apple 문서에 대한 [link] (https://developer.apple.com/library/ios/recipes/xcode_help-debugger/using_view_debugger/using_view_debugger.html)입니다.이 문서는 Apple 문서의 기본 사용법을 설명합니다. - David L –

+0

언제 수학을하고 있으며 새 버튼을 어떻게 배치하고 있습니까? 몇 가지 코드를 볼 수 있습니까? – jrturton

+0

자동 레이아웃으로 배치 된 뷰는 런타임과 마찬가지로 다른 위치와 마찬가지로 위치를보고합니다. center 속성은 버튼 수퍼 뷰의 좌표 공간에 저장됩니다. – jrturton

답변

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; 
} 
+0

이것은 정확히 물건이며, 매력처럼 작동합니다! 또한 프레임을 사용하는 또 다른 문제를 해결할 수 있습니다. 가변 크기의 버튼 크기는 X 위치만큼 오프셋되어 위치 지정됩니다. 이것은 IB가 아닌 코드로 제약 조건을 설정하는 방법에 대한 좋은 지식이기도합니다. 나는 여전히 Autolayout을 고를려고 노력하고있다. 그리고 IB에서 나는 그것을 알아 냈다. 그러나 나는 전에 이런 짓을하지 않았다. 감사합니다. 당신은 신사이자 학자입니다. :) – MonkRocker

-1

NSLayoutConstraints는 layoutSubviews 이후에 처리됩니다. 자동 레이아웃보기에서 NSLayoutConstraints를 제거하고 UIViewAutoresizingFlexible* 상수로 바꾸면 layoutSubviews 오버라이드 내에 [super layoutSubviews]을 호출하면 버튼의 프레임이 업데이트됩니다.

@jrturton 또한 센터 계산에 관한 위의 좋은 점을 제시합니다. 보고되는 센터가 수퍼 뷰의 중심이라는 불만 사항이 있으면 예상되는 동작입니다. 화면과 관련된 중심을 원하면 [[UIScreen mainScreen] convertPoint:point fromView:theView]을 사용하여 변환해야합니다.

+0

제약 조건 해결사는'layoutSubviews' 전에 실행됩니다. '- [UIView layoutSubviews]'는'self'의 서브 뷰에 솔루션을 적용합니다. 그래서'layoutSubviews'를 오버라이드하면'[super layoutSubviews]'를 호출해야합니다. –

+0

제 경험상 viewSubviews가 반환 된 후에 뷰 제약 조건이 적용됩니다. –