不同方向的自动布局约束集合

3
我看到了一个类似的帖子,但并不适用于我的情况。
因此,在不同的方向上有不同的屏幕布局。 应用程序使用storyboards。为了更好地理解,我附上UI示意图的照片 UI Sketch 正如您所见,存在TableView和Toolbar(自定义)。 工具栏包含2个标签和一个按钮。
因此,纵向模式约束条件为:
  • 工具栏高度为80pt
  • 工具栏尾部和前导空间==0
  • 从导航栏开始的TableView的顶部间距==0
  • 从工具栏开始的TableView的底部间距= 0
  • Tableview的宽度== Toolbar宽度
  • 标签在工具栏内垂直居中,具有固定大小和固定左右距离
  • 按钮在工具栏内具有固定尺寸并且居中
横向模式的约束条件完全不同:
  • 工具栏宽度80pt
  • 工具栏顶部(来自导航栏)和底部间距==0
  • 工具栏尾部空间==0
  • 从TableView开始的引导空间==0
  • Tableview的尾部空间(来自Toolbar)= 0
  • Tableview的高度== Toolbar宽度
  • 标签在工具栏内水平居中,具有固定大小和固定顶部和底部距离
  • 按钮在工具栏内具有固定尺寸并且居中
我试图从storyboard中删除所有约束,并以编程方式添加它们。但是Xcode会在编译期间自动添加它们。我试图删除根视图中的所有约束,但可能我没有正确地通过所有视图树,因为某些约束没有被删除。
您有任何想法如何以正确的方式实现这一点吗?
这是我的解决方案,它不起作用(因为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个回答

2
您正在使用的方法确实可行,但需要编写大量代码才能获得您想要的布局。更简单的方法是在xib文件中创建视图,分别为纵向和横向创建一个视图。您可以在那里设置所有约束,并且只需在代码中切换这两个视图。您可以在一个xib文件中创建这两个视图 - 我首先创建了纵向视图,因此它将是从加载nib返回的数组中的第一个对象。请注意,您应该删除故事板中控制器的视图(如果您想,可以将其复制并粘贴到xib文件中)。
@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
@OgreSwamp,也许是的,但在代码中实现并没有什么不同。我甚至不确定在旋转方向时是否可以进行交叉淡入淡出。 - rdelmar
嗯...在代码中执行(删除和设置约束)将默认具有动画效果。据我所知,如果更改约束,UIKit会进行动画处理。 我认为交叉淡入淡出应该是可能的 - 我可以截取屏幕截图,将其放置在新视图的顶部,并在0.5秒内将其透明度降低到0.0。 - OgreSwamp
@OgreSwamp,不,如果您更改约束(删除然后添加新的),或者更改常量值(除非在动画块中执行),则约束不会被动画化。您可能可以尝试截屏,这是我从未尝试过的事情。 - rdelmar
感谢您。使用这种方法发现了另一个问题。我在.xib中有IBOutlets。如果我在第二个.xib中连接相同的outlets并加载它们,那么我的控制器中的IBOutlets将引用最新加载的视图。 - OgreSwamp
@OgreSwamp,你可以为子视图添加标签,并根据这些标签设置属性(而不是插座)--我更新了我的答案以展示我是如何做到的。如果你将xib的文件所有者设置为你的视图控制器,你仍然可以连接两个视图中按钮的IBActions,但不幸的是,你不能用这种方式进行插座的连接。 - rdelmar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接