如何在屏幕中央呈现按钮?
How to render a Button on center of the screen?
我正在为我的应用程序使用 Google Sign In,默认情况下,当它呈现时,它看起来像附加的一样
我环顾四周,看看如何以编程方式添加约束,以便根据屏幕的大小,按钮落在屏幕中央,所以我的代码看起来像
- (void)signInWithGooglePlus {
GPPSignInButton *signInButton = [[GPPSignInButton alloc] init];
[signInButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[signInButton setStyle:kGPPSignInButtonStyleWide];
[signInButton setColorScheme:kGPPSignInButtonColorSchemeDark];
NSLayoutConstraint *vConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint *hConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[self.view addConstraint:vConstraint];
[self.view addConstraint:hConstraint];
[self.view addSubview:signInButton];
GPPSignIn *signIn = [GPPSignIn sharedInstance];
signIn.shouldFetchGooglePlusUser = YES;
signIn.shouldFetchGoogleUserEmail = YES;
signIn.clientID = kClientId;
signIn.scopes = @[@"profile"];
signIn.delegate = self;
[signIn trySilentAuthentication];
}
并在
中调用
- (void)viewDidLoad {
[super viewDidLoad];
[self signInWithGooglePlus];
}
当我 运行 它时,它失败了
2015-03-14 16:50:11.265 myapp-ios[24332:1661610] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7ff4c0c1b490 GPPSignInButton.centerY == UIView:0x7ff4c0f54930.centerY (Names: GPPSignInButton:0x7ff4c0f55da0 )>
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-03-14 16:50:11.267 myapp-ios[24332:1661610] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x7ff4c0c1b490 GPPSignInButton.centerY == UIView:0x7ff4c0f54930.centerY (Names: GPPSignInButton:0x7ff4c0f55da0 )>
Container hierarchy:
<UIView: 0x7ff4c0f54930; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff4c0f52d20>>
View not found in container hierarchy: <GPPSignInButton: 0x7ff4c0f55da0; baseClass = UIButton; frame = (0 0; 226 48); opaque = NO; layer = <CALayer: 0x7ff4c0f542b0>>
That view's superview: NO SUPERVIEW
2015-03-14 16:50:11.279 myapp-ios[24332:1661610] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0x7ff4c0c1b490 GPPSignInButton.centerY == UIView:0x7ff4c0f54930.centerY (Names: GPPSignInButton:0x7ff4c0f55da0 )> view:<UIView: 0x7ff4c0f54930; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff4c0f52d20>>'
*** First throw call stack:
(
0 CoreFoundation 0x000000010bb93a75 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010b828bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010bb939ad +[NSException raise:format:] + 205
3 Foundation 0x00000001094d5689 -[NSLayoutConstraint _addToEngine:integralizationAdjustment:mutuallyExclusiveConstraints:] + 187
4 UIKit 0x000000010a21bed5 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 474
5 Foundation 0x00000001094e32fe -[NSISEngine withBehaviors:performModifications:] + 155
6 UIKit 0x000000010a21bcdb __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452
7 UIKit 0x000000010a21baee -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197
8 UIKit 0x000000010a21b761 -[UIView(AdditionalLayoutSupport) _initializeHostedLayoutEngine] + 404
9 UIKit 0x000000010a21c281 -[UIView(AdditionalLayoutSupport) _layoutEngineCreateIfNecessary] + 53
10 UIKit 0x000000010a210bfa -[UIView(UIConstraintBasedLayout) _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:] + 156
11 UIKit 0x000000010a210f94 -[UIView(UIConstraintBasedLayout) _tryToAddConstraintWithoutUpdatingConstraintsArray:roundingAdjustment:mutuallyExclusiveConstraints:] + 30
12 UIKit 0x000000010a2110bc -[UIView(UIConstraintBasedLayout) _tryToAddConstraint:roundingAdjustment:mutuallyExclusiveConstraints:] + 243
13 myapp-ios 0x0000000108f0fd5d -[GooglePlusLoginViewController signInWithGooglePlus] + 557
14 myapp-ios 0x0000000108f0fa7b -[GooglePlusLoginViewController handleAuthentication] + 43
15 myapp-ios 0x0000000108f0fa44 -[GooglePlusLoginViewController viewDidLoad] + 228
16 UIKit 0x0000000109cba580 -[UIViewController loadViewIfRequired] + 738
17 UIKit 0x0000000109cba77e -[UIViewController view] + 27
18 UIKit 0x0000000109bd9509 -[UIWindow addRootViewControllerViewIfPossible] + 58
19 UIKit 0x0000000109bd98a1 -[UIWindow _setHidden:forced:] + 247
20 UIKit 0x0000000109be5f8c -[UIWindow makeKeyAndVisible] + 42
21 myapp-ios 0x0000000108f0f483 -[AppDelegate application:didFinishLaunchingWithOptions:] + 627
22 UIKit 0x0000000109b8f458 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 248
23 UIKit 0x0000000109b90002 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2540
24 UIKit 0x0000000109b92e3e -[UIApplication _runWithMainScene:transitionContext:completion:] + 1349
25 UIKit 0x0000000109b91d35 -[UIApplication workspaceDidEndTransaction:] + 179
26 FrontBoardServices 0x000000010f7a7243 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
27 CoreFoundation 0x000000010bac8c7c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
28 CoreFoundation 0x000000010babe9c5 __CFRunLoopDoBlocks + 341
29 CoreFoundation 0x000000010babe785 __CFRunLoopRun + 2389
30 CoreFoundation 0x000000010babdbc6 CFRunLoopRunSpecific + 470
31 UIKit 0x0000000109b917a2 -[UIApplication _run] + 413
32 UIKit 0x0000000109b94580 UIApplicationMain + 1282
33 myapp-ios 0x0000000108f0f1e3 main + 115
34 libdyld.dylib 0x000000010d104145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
问题
如何将 GPSSignInButton
置于屏幕中央?
编辑:
我发这个答案的时候不知道AutoLayout,请忽略它并使用constraints.
旧答案:
我从来没有使用过 NSLayoutConstraints,但是一个简单的方法来做你想做的事情是像这样设置你的按钮的框架原点:
[signInButton setFrameOrigin:CGPointMake((self.view.frame.size.width - signInButton.frame.size.width) / 2, (self.view.frame.size.height - signInButton.frame.size.height) / 2)];
您必须在创建约束之前将 signInButton 添加为子视图;这就是您收到该错误的原因。只需更改语句的顺序即可。
[self.view addSubview:signInButton];
NSLayoutConstraint *vConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint *hConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[self.view addConstraint:vConstraint];
[self.view addConstraint:hConstraint];
根据 @iSeven
的回答,我在我的代码中添加了以下内容
CGRect frame = signInButton.frame;
frame.origin.x = (self.view.frame.size.width - signInButton.frame.size.width) / 2;
frame.origin.y = (self.view.frame.size.height - signInButton.frame.size.height) / 2;
signInButton.frame = frame;
整个方法现在看起来像
- (void)signInWithGooglePlus {
GPPSignInButton *signInButton = [[GPPSignInButton alloc] init];
[signInButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[signInButton setStyle:kGPPSignInButtonStyleWide];
[signInButton setColorScheme:kGPPSignInButtonColorSchemeDark];
CGRect frame = signInButton.frame;
frame.origin.x = (self.view.frame.size.width - signInButton.frame.size.width) / 2;
frame.origin.y = (self.view.frame.size.height - signInButton.frame.size.height) / 2;
signInButton.frame = frame;
[self.view addSubview:signInButton];
GPPSignIn *signIn = [GPPSignIn sharedInstance];
signIn.shouldFetchGooglePlusUser = YES;
signIn.shouldFetchGoogleUserEmail = YES;
signIn.clientID = kClientId;
signIn.scopes = @[@"profile"];
signIn.delegate = self;
[signIn trySilentAuthentication];
}
我正在为我的应用程序使用 Google Sign In,默认情况下,当它呈现时,它看起来像附加的一样
我环顾四周,看看如何以编程方式添加约束,以便根据屏幕的大小,按钮落在屏幕中央,所以我的代码看起来像
- (void)signInWithGooglePlus {
GPPSignInButton *signInButton = [[GPPSignInButton alloc] init];
[signInButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[signInButton setStyle:kGPPSignInButtonStyleWide];
[signInButton setColorScheme:kGPPSignInButtonColorSchemeDark];
NSLayoutConstraint *vConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint *hConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[self.view addConstraint:vConstraint];
[self.view addConstraint:hConstraint];
[self.view addSubview:signInButton];
GPPSignIn *signIn = [GPPSignIn sharedInstance];
signIn.shouldFetchGooglePlusUser = YES;
signIn.shouldFetchGoogleUserEmail = YES;
signIn.clientID = kClientId;
signIn.scopes = @[@"profile"];
signIn.delegate = self;
[signIn trySilentAuthentication];
}
并在
中调用- (void)viewDidLoad {
[super viewDidLoad];
[self signInWithGooglePlus];
}
当我 运行 它时,它失败了
2015-03-14 16:50:11.265 myapp-ios[24332:1661610] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7ff4c0c1b490 GPPSignInButton.centerY == UIView:0x7ff4c0f54930.centerY (Names: GPPSignInButton:0x7ff4c0f55da0 )>
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-03-14 16:50:11.267 myapp-ios[24332:1661610] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x7ff4c0c1b490 GPPSignInButton.centerY == UIView:0x7ff4c0f54930.centerY (Names: GPPSignInButton:0x7ff4c0f55da0 )>
Container hierarchy:
<UIView: 0x7ff4c0f54930; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff4c0f52d20>>
View not found in container hierarchy: <GPPSignInButton: 0x7ff4c0f55da0; baseClass = UIButton; frame = (0 0; 226 48); opaque = NO; layer = <CALayer: 0x7ff4c0f542b0>>
That view's superview: NO SUPERVIEW
2015-03-14 16:50:11.279 myapp-ios[24332:1661610] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0x7ff4c0c1b490 GPPSignInButton.centerY == UIView:0x7ff4c0f54930.centerY (Names: GPPSignInButton:0x7ff4c0f55da0 )> view:<UIView: 0x7ff4c0f54930; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff4c0f52d20>>'
*** First throw call stack:
(
0 CoreFoundation 0x000000010bb93a75 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010b828bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010bb939ad +[NSException raise:format:] + 205
3 Foundation 0x00000001094d5689 -[NSLayoutConstraint _addToEngine:integralizationAdjustment:mutuallyExclusiveConstraints:] + 187
4 UIKit 0x000000010a21bed5 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 474
5 Foundation 0x00000001094e32fe -[NSISEngine withBehaviors:performModifications:] + 155
6 UIKit 0x000000010a21bcdb __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452
7 UIKit 0x000000010a21baee -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197
8 UIKit 0x000000010a21b761 -[UIView(AdditionalLayoutSupport) _initializeHostedLayoutEngine] + 404
9 UIKit 0x000000010a21c281 -[UIView(AdditionalLayoutSupport) _layoutEngineCreateIfNecessary] + 53
10 UIKit 0x000000010a210bfa -[UIView(UIConstraintBasedLayout) _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:] + 156
11 UIKit 0x000000010a210f94 -[UIView(UIConstraintBasedLayout) _tryToAddConstraintWithoutUpdatingConstraintsArray:roundingAdjustment:mutuallyExclusiveConstraints:] + 30
12 UIKit 0x000000010a2110bc -[UIView(UIConstraintBasedLayout) _tryToAddConstraint:roundingAdjustment:mutuallyExclusiveConstraints:] + 243
13 myapp-ios 0x0000000108f0fd5d -[GooglePlusLoginViewController signInWithGooglePlus] + 557
14 myapp-ios 0x0000000108f0fa7b -[GooglePlusLoginViewController handleAuthentication] + 43
15 myapp-ios 0x0000000108f0fa44 -[GooglePlusLoginViewController viewDidLoad] + 228
16 UIKit 0x0000000109cba580 -[UIViewController loadViewIfRequired] + 738
17 UIKit 0x0000000109cba77e -[UIViewController view] + 27
18 UIKit 0x0000000109bd9509 -[UIWindow addRootViewControllerViewIfPossible] + 58
19 UIKit 0x0000000109bd98a1 -[UIWindow _setHidden:forced:] + 247
20 UIKit 0x0000000109be5f8c -[UIWindow makeKeyAndVisible] + 42
21 myapp-ios 0x0000000108f0f483 -[AppDelegate application:didFinishLaunchingWithOptions:] + 627
22 UIKit 0x0000000109b8f458 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 248
23 UIKit 0x0000000109b90002 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2540
24 UIKit 0x0000000109b92e3e -[UIApplication _runWithMainScene:transitionContext:completion:] + 1349
25 UIKit 0x0000000109b91d35 -[UIApplication workspaceDidEndTransaction:] + 179
26 FrontBoardServices 0x000000010f7a7243 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
27 CoreFoundation 0x000000010bac8c7c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
28 CoreFoundation 0x000000010babe9c5 __CFRunLoopDoBlocks + 341
29 CoreFoundation 0x000000010babe785 __CFRunLoopRun + 2389
30 CoreFoundation 0x000000010babdbc6 CFRunLoopRunSpecific + 470
31 UIKit 0x0000000109b917a2 -[UIApplication _run] + 413
32 UIKit 0x0000000109b94580 UIApplicationMain + 1282
33 myapp-ios 0x0000000108f0f1e3 main + 115
34 libdyld.dylib 0x000000010d104145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
问题
如何将 GPSSignInButton
置于屏幕中央?
编辑:
我发这个答案的时候不知道AutoLayout,请忽略它并使用constraints.
旧答案: 我从来没有使用过 NSLayoutConstraints,但是一个简单的方法来做你想做的事情是像这样设置你的按钮的框架原点:
[signInButton setFrameOrigin:CGPointMake((self.view.frame.size.width - signInButton.frame.size.width) / 2, (self.view.frame.size.height - signInButton.frame.size.height) / 2)];
您必须在创建约束之前将 signInButton 添加为子视图;这就是您收到该错误的原因。只需更改语句的顺序即可。
[self.view addSubview:signInButton];
NSLayoutConstraint *vConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint *hConstraint = [NSLayoutConstraint constraintWithItem:signInButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[self.view addConstraint:vConstraint];
[self.view addConstraint:hConstraint];
根据 @iSeven
的回答,我在我的代码中添加了以下内容
CGRect frame = signInButton.frame;
frame.origin.x = (self.view.frame.size.width - signInButton.frame.size.width) / 2;
frame.origin.y = (self.view.frame.size.height - signInButton.frame.size.height) / 2;
signInButton.frame = frame;
整个方法现在看起来像
- (void)signInWithGooglePlus {
GPPSignInButton *signInButton = [[GPPSignInButton alloc] init];
[signInButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[signInButton setStyle:kGPPSignInButtonStyleWide];
[signInButton setColorScheme:kGPPSignInButtonColorSchemeDark];
CGRect frame = signInButton.frame;
frame.origin.x = (self.view.frame.size.width - signInButton.frame.size.width) / 2;
frame.origin.y = (self.view.frame.size.height - signInButton.frame.size.height) / 2;
signInButton.frame = frame;
[self.view addSubview:signInButton];
GPPSignIn *signIn = [GPPSignIn sharedInstance];
signIn.shouldFetchGooglePlusUser = YES;
signIn.shouldFetchGoogleUserEmail = YES;
signIn.clientID = kClientId;
signIn.scopes = @[@"profile"];
signIn.delegate = self;
[signIn trySilentAuthentication];
}