我正在创建一个iPhone应用程序,在一个视图中我计划有一个分屏。它将是页面主要区域中的地图视图,但我想在地图下方显示一个表格,该表格显示最近用户点击的详细信息。
因此纵向视图中的布局将如下所示:
------------
| |
| |
| |
| |
| |
| |
| |
------------
| |
| |
| |
------------
在顶部mapview区域和底部表区域之间进行60/40分割。
当我旋转手机时,我需要这种布局来重新调整和合理旋转,以便调整为:
---------------------------
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
---------------------------
左侧区域的mapview和右侧的表格。
当然,当用户旋转设备时,可以平滑地重新布局两个视图。
在代码中处理此问题的最佳方法是什么?我不确定在旋转时重新布局屏幕的最佳方法是什么?
使用例如顶视图来调整和移动两个视图是不错的做法:
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight*0.6)];
然后在检测到方向更改时使用以下内容移动并重绘:
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, screenWidth*0.6, screenHeight)];
答案 0 :(得分:0)
您希望自己的UI适应。 Apple wants your UI to adapt.
您可以编写代码来处理方向更改并自己创建视图,但是您可能会错过边缘情况,或者它可能无法在将来的设备或即将推出的功能(例如分屏多任务处理)上运行。 / p>
您可能希望利用UIStackView
而不是尝试编写代码来处理此问题。
通过堆栈视图,您可以利用自动布局的强大功能,创建可以动态适应设备方向的用户界面,屏幕大小以及可用空间的任何变化。
答案 1 :(得分:0)
使用具有多个约束数组的Autolayout可以实现完全相同的行为。只需保存自己应用的 NSLayoutConstraint 的引用。让我们假设您已将视图声明为属性并合成它们,如下所示。
@interface YourFancySplitScreenViewController ()
@property (nonatomic, strong) AwesomeMapView* myAwesomeMapView;
@property (nonatomic, strong) CoolTableView* myCoolTableView;
@property (nonatomic, strong) NSMutableArray* portraitLayoutConstraints;
@property (nonatomic, strong) NSMutableArray* landscapeLayoutConstraint;
@end
@implementation YourFancySplitScreenViewController
@synthesize myAwesomeMapView, myCoolTableView;
@synthesize portraitLayoutConstraints, landscapeLayoutConstraint;
// [...]
@end
只需设置您的视图并将其添加为 UIViewController.view 的子视图。在此之后,使用适当的约束条件填充数组 portraitLayoutConstraints 和 landscapeLayoutConstraint 。
- (void) getYourConstraintsRight {
// The Views you want to manipulate with your Constraints
NSDictionary* viewsDictionary = NSDictionaryOfVariableBindings(myAwesomeMapView, myCoolTableView);
self.portraitLayoutConstraints = [[NSMutableArray alloc] init];
self.landscapeLayoutConstraint = [[NSMutableArray alloc] init];
// Now just add The Constraints to your Arrays, eg. with constraintsWithVisualFormat
[self.portraitLayoutConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"Your terrific portrait Contstraints" options:0 metrics:0 views:viewsDictionary]];
[self.landscapeLayoutConstraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"Your even better landscape Contstraints" options:0 metrics:0 views:viewsDictionary]];
}
在我目前的项目中,我将 portraitLayoutConstraints 添加到视图中。在此之后,我从同一个数组中取消激活约束。之后我可以添加 landscapeLayoutConstraint 并停用它们。这肯定不是实现预期行为的最优雅方式,但它对我有用。设置好Constraints后,我可以根据需要停用并激活它们。
- (void) addYourConstraintsToTheView {
// place some ugly code here
[self.view addConstraints:self.landscapeLayoutConstraint];
[NSLayoutConstraint deactivateConstraints:self.landscapeLayoutConstraint];
[self.view addConstraints:self.portraitLayoutConstraints];
[NSLayoutConstraint deactivateConstraints:self.portraitLayoutConstraints];
}
- (void) setYourConstraintsAccordingToTheUIInterfaceOrientation {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
[NSLayoutConstraint activateConstraints:self.landscapeLayoutConstraint];
}
if (orientation == UIInterfaceOrientationPortrait) {
[NSLayoutConstraint activateConstraints:self.portraitLayoutConstraints];
}
}
在我的特殊情况下,我想对DeviceOrientation的更改作出反应,因此我在 viewDidLoad 中添加了 UIApplicationWillChangeStatusBarOrientationNotification 的观察者,并在此时停用/激活约束DeviceOrientation更改。
- (void)viewDidLoad {
[super viewDidLoad];
// Maybe you want to set your views here
// then add the Constraints
[self getYourConstraintsRight];
[self addYourConstraintsToTheView];
[self setYourConstraintsAccordingToTheUIInterfaceOrientation];
// Observe your Notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notification_OrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
}
- (void)notification_OrientationWillChange:(NSNotification*)notification {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];;
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
[self animateToPortrait];
}
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
[self animateToLandscape];
}
}
- (void)animateToPortrait {
[UIView animateWithDuration:1.0 animations:^{
[NSLayoutConstraint deactivateConstraints: self.landscapeLayoutConstraint];
[NSLayoutConstraint activateConstraints: self.portraitLayoutConstraints];
}];
[self.view layoutIfNeeded];
}
- (void)animateToLandscape {
[UIView animateWithDuration:1.0 animations:^{
[NSLayoutConstraint deactivateConstraints: self.portraitLayoutConstraints];
[NSLayoutConstraint activateConstraints: self.landscapeLayoutConstraint];
}];
[self.view layoutIfNeeded];
}
// You want to remove the Observer
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisapper:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self.view];
}
也许这有助于为您的问题找到解决方案。我在Portrait Orientation的可用指示范围中看到的另一个困难。如果您考虑拥抱滚动视图中的内容,请查看我的答案:Adding programatically created views into scrollview vertically。我还建议Mysteries of Auto Layout上的WWDC2015会话和相应的AstroLayout Sample code。