Xcode 5 Autolayout:另一个视图中的视图集合

时间:2014-03-17 23:02:46

标签: iphone objective-c ios7 autolayout

我有一组代表卡片的视图,这些视图应该都符合它的超级视图:

enter image description here

我希望容器视图在屏幕中心附近对齐,所以我为它添加了这些约束:

  • 用它的容器领导空间;
  • 带有布局指南的顶部空间(视图控制器位于导航控制器内);
  • 在容器中水平居中;
  • 在容器中垂直居中。

这样,包含所有其他小视图的视图以某种方式固定,并且在横向模式下,它变得更小,因此它的子视图应该垂直缩小很多。

我在视图中的所有子视图中添加了这些约束:

  • 相同宽度;
  • 相同的高度;
  • 带有任何邻居视图的前导,尾随,顶部和底部空间。

为了让最后一步更清楚,我还要添加这张图片:

enter image description here

现在第一个问题是,当iphone模拟器旋转到横向时,所有视图都会缩小:

enter image description here

我理解为什么:来自邻居的顶部和垂直空间有一个标准值,可能在横向模式下相对于可用的垂直空间太高,因此它们太短。但是如何指定以百分比形式占空间的约束(例如:垂直间距:视图宽度的5%)?在我的情况下,最好的做法是调整子视图的大小,就像它们被缩放以适应新的子视图边界一样。我该怎么做?

另一个问题是如果我将它旋转到横向然后将其颠倒过来,应用程序会崩溃:

2014-03-17 23:40:04.736 Matchismo[10284:60b] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x109226d90 V:|-(NSSpace(20))-[PlayingCardView:0x109224330]   (Names: '|':UIView:0x109226610 )>",
    "<NSLayoutConstraint:0x109226e80 V:[PlayingCardView:0x109224330]-(NSSpace(8))-[PlayingCardView:0x109225080]>",
    "<NSLayoutConstraint:0x109227150 V:[PlayingCardView:0x109225080]-(NSSpace(8))-[PlayingCardView:0x109225700]>",
    "<NSLayoutConstraint:0x1092277e0 V:[PlayingCardView:0x109225d80]-(NSSpace(20))-|   (Names: '|':UIView:0x109226610 )>",
    "<NSLayoutConstraint:0x109227830 PlayingCardView:0x109225d80.height == PlayingCardView:0x109225700.height>",
    "<NSLayoutConstraint:0x109227970 PlayingCardView:0x109225d80.height == PlayingCardView:0x109224330.height>",
    "<NSLayoutConstraint:0x109227ba0 PlayingCardView:0x109225d80.height == PlayingCardView:0x109225080.height>",
    "<NSLayoutConstraint:0x109227ce0 V:[PlayingCardView:0x109225700]-(NSSpace(8))-[PlayingCardView:0x109225d80]>",
    "<NSLayoutConstraint:0x10922a0e0 UIView:0x109228f40.centerY == UIView:0x109226610.centerY + 32>",
    "<NSLayoutConstraint:0x10922a130 V:[_UILayoutGuide:0x109229020]-(14)-[UIView:0x109226610]>",
    "<_UILayoutSupportConstraint:0x109224980 V:[_UILayoutGuide:0x109229020(64)]>",
    "<_UILayoutSupportConstraint:0x109221ff0 V:|-(0)-[_UILayoutGuide:0x109229020]   (Names: '|':UIView:0x109228f40 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x10923eef0 h=--& v=--& V:[UIView:0x109228f40(271)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x109227ce0 V:[PlayingCardView:0x109225700]-(NSSpace(8))-[PlayingCardView:0x109225d80]>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
(lldb)  

但我无法看到任何相互矛盾的约束。

解决方案

利用ReedD的答案,我决定使用集合视图。这是我遇到的解决方案(在我的情况下,我需要在4x4集合视图中使用16张卡,但代码可以重新排列以通用方式工作):

- (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 4;
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 4;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell* cell= [collectionView dequeueReusableCellWithReuseIdentifier:@"reuseIdentifier" forIndexPath:indexPath];

    <Initialize the card view and add it to the cell>

    return cell;
}

- (CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return CGSizeMake(collectionView.contentSize.width/4.0 -5.0,collectionView.contentSize.height/4.0 -5.0);
}

- (UIEdgeInsets) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(5, 5, 5, 5);
}

3 个答案:

答案 0 :(得分:2)

解决您的上一个问题:

如果您在崩溃日志中看到以下内容 -

"<NSAutoresizingMaskLayoutConstraint:0x10923eef0 h=--& v=--& V:[UIView:0x109228f40(271)]>"

- 你的第一个预感就是为内存地址为0x109228f40的视图写下这一行

self.view.translatesAutoresizingMaskIntoConstraints= NO;

答案 1 :(得分:1)

您是否尝试在第一张卡片上设置高度限制并将其设置为&gt; = 20(或任何可能合理的最小值)? 此外,得分和新游戏按钮是否以任何方式限制在卡片容器中?如果是这样,您应该尝试删除它们之间的任何垂直间距。

答案 2 :(得分:1)

您是否考虑过使用UICollectionView?然后使用数据源委托,你可以做一些事情:

#pragma mark - UICollectionViewDatasource

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout  *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
        // Landscape
        return CGSizeMake(50, 100);
    }
    // Portrait
    return CGSizeMake(100, 200);
}