我知道当方向改变时,自动布局可用于使尺寸和位置保持一致。方向改变时是否可以完全改变布局?
例如,请看下面一个简单的纵向模式登录屏幕的线框图。
现在,如果我旋转设备,我想完全重新定位控件。
这种事情可以通过使用自动布局来完成吗?如果没有,我该怎么做?
谢谢你。
我知道当方向改变时,自动布局可用于使尺寸和位置保持一致。方向改变时是否可以完全改变布局?
例如,请看下面一个简单的纵向模式登录屏幕的线框图。
现在,如果我旋转设备,我想完全重新定位控件。
这种事情可以通过使用自动布局来完成吗?如果没有,我该怎么做?
谢谢你。
在您的情况下,可以通过两种方法来实现,而不是重新构建每个组件,您可以对控件进行分组,如下所示..
父视图-> 用户信息视图-> 所有用户信息控件.. 通过这样做,您只需重新构建用户信息视图而不是所有控件..
然后只剩下徽标和公司名称需要重新构建。如果您对控件进行分组,总共需要重新构建 3 个控件。
创建两个视图,一个用于纵向模式,另一个用于横向模式,只需添加和删除旋转。这是最快的方法,因为您不必通过繁琐的代码重新调整框架。
以上希望有所帮助。
你不能以不同的方式设置框架:-
-(void)setFramesForPotrait
{
// set frames here
}
-(void)setFramesForLandscaeMode
{
// set frames here
}
-(bool)shouldAutorotate.....
{
return Yes
}
-()willAutoRotate......
{
if(orientation = uiinterfaceOrientationPotrait)
{
[self setFramesForPotrait];
}
else
{
[self setFramesForLandscape];
}
我遇到了同样的问题,这就是我到目前为止所发现的。我正在使用的方法是针对不同的屏幕尺寸或方向设置两组(可能是多组)约束。所以我只是为纵向设计并将所有纵向特定的约束连接到 IBOutletCollection: 然后将 InterfaceBuilder 中的 VC 方向切换为 Landscape 并为此方向添加所需的约束并连接到相应的插座:
然后在代码中,我根据需要删除或添加约束:
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self updateViewConstraints];
}
- (void)updateViewConstraints
{
[super updateViewConstraints];
if (self.view.frame.size.width >= kSize * 2 + kPadding * 3)
{
[self.view removeConstraints:self.constraintsForPortrait];
[self.view addConstraints:self.constraintsForLandscape];
} else
{
[self.view removeConstraints:self.constraintsForLandscape];
[self.view addConstraints:self.constraintsForPortrait];
}
}
您可以使用此代码获得类似的结果,基于方向而不是框架大小添加/删除约束:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self updateViewConstraints];
}
但请记住,有传言称苹果将发布具有不同屏幕纵横比的设备并废弃 UIInterfaceOrientation 和旋转事件,这可能值得提前准备。将看到未来会带来什么。
这种方法的缺点是 Xcode 会抱怨设计模棱两可,实际上是这样,因为 Xcode 不知道我们将在运行时消除模棱两可。为了解决这个问题,您可以将约束的优先级设置为对于您在此特定时刻未设计的所有其他方向是可选的(例如,如果您正在为纵向设计,则为横向选择约束)。
使用自动布局时,您可以覆盖 updateViewConstraints以在方向更改时修改布局:
- (void)updateViewConstraints{
[super updateViewConstraints];
//portrait
if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
}
//landscape
else{
//
}
}
它可以通过布局约束来完成,如下所示。这不太有效,因为您的草图不太有效 - 与您在风景中实际看到的相比,您的风景视图太长了。您必须缩短登录文本字段以适应所有内容,但这应该让您了解它是如何完成的。buttonWidth 约束显示了如何在视图的宽度和按钮的宽度之间建立负相关关系——也就是说,按钮的宽度在横向比纵向要小。我有几个 IBOutlets 到我在代码中引用的约束。如果您有兴趣,我可以为您描述它们,但我现在就把它扔在那里:
@implementation ViewController {
IBOutlet NSLayoutConstraint *buttonWidth;
IBOutlet NSLayoutConstraint *logoTop;
IBOutlet NSLayoutConstraint *logoAlignToLabel;
IBOutlet NSLayoutConstraint *logoSpaceToLabel;
IBOutlet NSLayoutConstraint *coNameToButtonAlignment;
IBOutlet UIButton *b;
IBOutlet UIImageView *logo;
IBOutlet UILabel *coName;
NSLayoutConstraint *con2;
NSArray *cons1;
}
- (void)viewDidLoad {
[super viewDidLoad];
[b removeConstraint:buttonWidth];
buttonWidth = [NSLayoutConstraint constraintWithItem:b attribute:NSLayoutAttributeWidth relatedBy:0 toItem:self.view attribute:NSLayoutAttributeWidth multiplier:-.2193 constant:350];
[self.view addConstraint:buttonWidth];
[self.view layoutSubviews];
}
- (void)updateViewConstraints{
[super updateViewConstraints];
if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
if (con2 != nil) {
[self.view removeConstraints:cons1];
[self.view removeConstraint:con2];
[self.view addConstraints:@[logoAlignToLabel,logoSpaceToLabel,logoTop,coNameToButtonAlignment]];
}
}else{
NSLog(@"Landscape");
[self.view removeConstraints:@[logoAlignToLabel,logoSpaceToLabel,logoTop,coNameToButtonAlignment]];
cons1 = [NSLayoutConstraint constraintsWithVisualFormat:@"|-8-[logo]-4-[coName]" options:NSLayoutFormatAlignAllCenterY metrics:0 views:@{@"logo":logo, @"coName":coName}];
con2 = [NSLayoutConstraint constraintWithItem:logo attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
[self.view addConstraints:cons1];
[self.view addConstraint:con2];
}
}
在轮换时,徽标和公司名称标签的约束被移除,新的约束被放置到位。我在 viewDidLoad 中添加的按钮的新约束会自动处理旋转,因此在旋转过程中我根本不需要调整它。