针对不同方向的不同自动布局约束集
Posted
技术标签:
【中文标题】针对不同方向的不同自动布局约束集【英文标题】:Different sets of auto layout constraints for different orientation 【发布时间】:2014-05-20 23:38:56 【问题描述】:我见过类似的post,但与我的情况不太接近
所以我有不同方向的不同屏幕布局。应用程序正在使用故事板。 为了更好地理解,我附上了 UI 草图的照片
如您所见,有一个 TableView 和一个 Toolbar(自定义)。工具栏包含 2 个标签和一个按钮。
所以纵向约束是:
工具栏高度 80pts 工具栏尾随和前导空格 == 0 导航栏的表格视图顶部空间 == 0 Toolbar 中 TableView 的底部空间 = 0 Tableview 的宽度 == 工具栏宽度 标签在工具栏内垂直居中,大小固定,左右距离固定 按钮具有固定大小并在工具栏内居中景观限制完全不同:
工具栏宽度 80pts 工具栏顶部(来自导航栏)和底部空间 == 0 工具栏尾随空格 == 0 TableView 的前导空格 == 0 TableView 从 Toolbar 的尾随空格 = 0 Tableview 的高度 == 工具栏的宽度 标签在工具栏内水平居中,大小固定,与顶部和底部的距离固定 按钮具有固定大小并在工具栏内居中我尝试从情节提要中删除所有约束并以编程方式添加它们。但是 Xcode 在编译过程中会自动添加它们。我试图删除根视图中的所有约束,但可能我没有正确浏览所有视图树,因为有几个约束没有被删除。
您知道如何以适当的方式实施吗?
这是我第一次使用 Auto Layout,它并不像我想象的那么容易。
这里我的解决方案不起作用(因为 Xcode 在编译期间添加了一些约束)
// Those properties store all constraints for portrait and landscape modes
@property (nonatomic, strong) NSArray *portraitConstraints;
@property (nonatomic, strong) NSArray *landscapeConstraints;
-(void)updateViewConstraints
[super updateViewConstraints];
BOOL layoutIsPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);
if (layoutIsPortrait)
for (NSLayoutConstraint *constraint in self.landscapeConstraints)
[constraint remove];
for (NSLayoutConstraint *constraint in self.portraitConstraints)
[constraint install];
else
for (NSLayoutConstraint *constraint in self.portraitConstraints)
[constraint remove];
for (NSLayoutConstraint *constraint in self.landscapeConstraints)
[constraint install];
- (NSArray *)portraitConstraints
if (!_portraitConstraints)
UIView *mainTable = self.myTableView;
UIView *toolbar = self.toolbarView;
UIView *firstLabel = self.firstLabel;
UIView *secondLabel = self.secondLabel;
UIView *bigButton = self.bigButton;
UIView *navBar = self.navigationController.navigationBar;
NSDictionary *views = NSDictionaryOfVariableBindings(mainTable,toolbar,firstLabel,secondLabel,bigButton,navBar);
NSMutableArray *constraints = [NSMutableArray array];
[constraints addObjectsFromArray:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:[toolbar(==80)]|"
options:0
metrics:nil
views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:[navBar][mainTable][toolbar]|"
options:0
metrics:nil
views:views]];
// MORE AND MORE CONSTRAINTS ADDED HERE
_portraitConstraints = constraints;
return _portraitConstraints;
【问题讨论】:
【参考方案1】:您使用的方法当然是可行的,但会涉及大量代码来获得您正在寻找的布局。一种更简单的方法是在情节提要中删除控制器的视图(如果需要,可以将其复制并粘贴到 xib 文件中),而是在 xib 文件中创建其视图,分别用于纵向和横向。您可以在那里进行所有约束设置,并且只需要在代码中的两个视图之间切换。您可以在一个 xib 文件中创建两个视图——我首先创建了一个肖像,因此它将是您从加载 nib 得到的数组中的第一个对象。
@interface ViewController ()
@property (strong,nonatomic) UIView *pView;;
@property (strong,nonatomic) UIView *lView;
@property (strong,nonatomic) UILabel *leftLabel;
@property (strong,nonatomic) UILabel *rightLabel;
@end
@implementation ViewController
- (void)loadView
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"PortraitAndLandscapeViews" owner:self options:nil];
self.pView = views[0];
self.lView = views[1];
self.view = self.pView;
-(void)viewWillLayoutSubviews
BOOL layoutIsPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);
if (layoutIsPortrait)
self.view = self.pView;
self.leftLabel = [self.view viewWithTag:11];
self.rightLabel = [self.view viewWithTag:12];
else
self.view = self.lView;
self.leftLabel = [self.view viewWithTag:21];
self.rightLabel = [self.view viewWithTag:22];
【讨论】:
谢谢!这是个好主意。但这意味着只有可能(和适当)的过渡动画才会交叉淡入淡出。我说的对吗? @OgreSwamp,也许是的,但在代码中执行它不会有任何不同。我什至不确定您是否可以在方向之间旋转期间进行交叉淡入淡出。 嗯...在代码中执行此操作(删除和设置约束)默认情况下会有动画。据我所知,如果您更改约束,UIKit 会制作动画。我认为交叉淡入淡出应该是可能的 - 我可以制作屏幕截图,将其设置在新视图的顶部并在 0.5 秒内将 alfa 减小到 0.0。 @OgreSwamp,不,如果您更改约束(删除然后添加新约束)或更改常量值(除非您在动画块中执行此操作),约束不会被动画化。你也许可以做屏幕截图的事情,这是我从未尝试过的事情。 谢谢。发现这种方法的另一个问题。我的 .xib 中有 IBOutlets。如果我在第二个 .xib 中连接相同的插座并加载它们 - 我的控制器中的 IBOutlets 将引用最新加载的视图。以上是关于针对不同方向的不同自动布局约束集的主要内容,如果未能解决你的问题,请参考以下文章