【问题标题】:Xcode 5 Autolayout : collection of views inside another viewXcode 5 Autolayout:另一个视图中的视图集合
【发布时间】:2014-04-23 09:59:13
【问题描述】:

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

我希望容器视图在屏幕中心附近对齐,因此我为其添加了以下约束:

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

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

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

  • 等宽;
  • 同样的高度;
  • 具有任何相邻视图的前导、尾随、顶部和底部空间。

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

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

我明白为什么:邻居的顶部和垂直空间有一个标准值,可能在横向模式下相对于可用的垂直空间来说太高了,所以它们太短了。但是我如何指定一个占空间百分比的约束(例如:垂直分隔:视图宽度的 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);
}

【问题讨论】:

    标签: iphone objective-c ios7 autolayout


    【解决方案1】:

    解决您的最后一个问题:

    当您在崩溃日志中看到以下内容时 -

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

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

    self.view.translatesAutoresizingMaskIntoConstraints= NO;
    

    【讨论】:

    • 会回答的。
    • 内存地址为 0x109228f40 的视图是导致此问题的原因。您的应用程序肯定将 Autoresizing 蒙版与 Autolayout 约束混合在一起。如果您已经解决了这个问题,那么您的崩溃日志现在应该会有所不同。你能分享一下你现在得到的东西吗?
    • 我和以前一样,它仍然崩溃。
    【解决方案2】:

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

    【讨论】:

    • 高度约束与“垂直对齐”约束冲突,我删除了它,它可以工作。
    【解决方案3】:

    你有没有想过可能使用 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);
    }
    

    【讨论】:

    • 就是这样。但是,请更正您验证它是处于横向还是纵向模式的部分,正确的方法是检查集合视图边界并正确创建子框架。
    • 嗯,也许我不明白你为什么要更正它。以下是使用相同方法的另外两个解决方案。 stackoverflow.com/a/13656570/3322075stackoverflow.com/a/22505766/3322075
    • 我使用了一个稍微不同的实现,它适用于每个视图大小。这样代码是可重用的,因为集合视图可能有不同的大小,它可能需要更小的单元格。但是这个答案真的很有启发性,所以我会给你赏金。
    • 太棒了,我很高兴它帮助您找到了一个可行的解决方案。也许您可以分享您的解决方案如何与此不同/改进。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多