【问题标题】:iOS two views cover exactly half of parent viewiOS 两个视图正好覆盖了父视图的一半
【发布时间】:2013-05-22 02:43:48
【问题描述】:

在我的应用中我想实现这个布局:

所以父视图包含两个子视图。第一个恰好在中间(高度/ 2)结束,第二个在父视图的中间开始。我发现在有限制的 IB 中是不可能做到这一点的。所以我在viewDidLoad方法中使用了这段代码:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstView
                                                              attribute:NSLayoutAttributeHeight
                                                              relatedBy:0
                                                                 toItem:self.view
                                                              attribute:NSLayoutAttributeHeight
                                                             multiplier:0.5
                                                               constant:0];

[self.view addConstraint:constraint];

现在它可以工作,但前提是应用程序在 iPhone 上运行。因为视图的大小就像 iPhone 屏幕。如果此应用程序在 iPad 上运行,则会出现问题,因为屏幕大小不同,因此此父视图较长。并且约束(上面的代码)仍然需要 0.5 * 来自 IB 的视图大小,而不是来自 iPad 视图大小的大小。项目 toItem:self.view 仍然从 IB 获取大小。

结果是此视图在 iPad 中的大小与在 iPhone 中的大小相同。在 iPad 中有一个很大的空白区域,然后有一个 iPhone 大小的视图。

您能告诉我必须做什么才能使其适用于各种屏幕尺寸吗?非常感谢

【问题讨论】:

    标签: ios layout view constraints


    【解决方案1】:

    你有两个选择。

    1. 为 iPad 创建第二个 IB 文件
    2. 通过程序执行所有操作并使用[[UIScreen mainScreen] bound]; 而不是获取父级的大小;)

    我会在没有约束的情况下这样做,并设置如下:

    // self.view is my container view
    
    CGRect frame = [[UIScreen mainScreen] bound];
    frame.size.height /= 2;    
    
    // upper View
    upperView.frame = frame;
    
    // lower View
    frame.origin.y = frame.size.height;
    // or alternatively
    //frame.origin.y = CGRectGetMaxY(frame);
    lowerView.frame = frame;
    

    在这里您不需要任何特定于设备的选项,一切都是动态的,与您设备的屏幕大小相关;)

    【讨论】:

    • 我试着把它放到viewController里面的viewDidLoad里面,什么也没发生。
    【解决方案2】:

    试试这个代码。它会动态设置约束值

    在您的 .h 文件中,实现这一行。

      #define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
      #define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
    
    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *TopsubviewheightConstraint;
    

    现在根据给定的屏幕截图创建此约束

    从屏幕连接 TopsubviewheightConstraint 高度约束

    在 .m 文件中实现此代码

    if (IS_IPHONE_5) 
        _TopSuperViewConstraint.constant = 275;
    else if(IS_IPAD)
        _TopSuperViewConstraint.constant = 502;
    else
        _TopSuperViewConstraint.constant = 230;
    

    希望对你有帮助。

    【讨论】:

    • 但如果我想在 iPhone 3/4/5、iPad、方向... 有许多不同的屏幕尺寸,而不仅仅是 iPhone/iPad 一种。
    • 您也可以为 NSLayoutConstraint 创建 IBOutlet,将 Constraint 与它的 IB 连接后,您可以动态更改其常量值。
    • 我不知道。所以我为约束创建了 IBOtlet,用我的问题(高度 * 0.5)中的代码对其进行初始化,将其分配给子视图,接下来呢?如果我稍后更改此约束,视图的大小将根据更改的约束自动更改?
    • 一般情况下没有机会吗?对于每种类型的屏幕,您都知道没有 if 语句。有一个父视图,如果获取此视图的大小,我知道子视图的大小
    • 将一个视图拆分为中间的两个视图是一个非常愚蠢的问题,在我看来这是相当多的代码......
    【解决方案3】:

    好的,所以我只是想出了如何做到这一点。只需将代码放入viewDidLayoutSubviews 方法而不是viewDidLoad。我在主题Unable to set frame correctly before viewDidAppear找到的解决方案。

    这是我的代码:

    [subView1 setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height / 2)];
    [subView2 setFrame:CGRectMake(0, self.view.frame.size.height / 2, self.view.frame.size.width, self.view.frame.size.height / 2)];
    

    感谢大家的努力!

    【讨论】:

    • 这段代码没有使用自动布局,因此每次布局发生时都应该运行,这是低效的。
    【解决方案4】:

    这可以使用约束来实现,但是 IB 让这变得有点繁琐,相当烦人且不灵活的约束管理器。以下是我的管理方式:

    • 在 IB 中,使用正确的框架设置两个视图
    • 在两个视图之间添加等高约束
    • 降低任一视图上任何默认高度约束的优先级。不幸的是,IB 不允许您完全删除这些,但是将它们设置为小于 1000 将确保它们被忽略。
    • 在视图控制器的 viewDidLoad 方法中,添加您已经尝试过的约束。

    例如

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.topView
                                                                      attribute:NSLayoutAttributeHeight
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:self.view
                                                                      attribute:NSLayoutAttributeHeight
                                                                     multiplier:0.5
                                                                       constant:0];
        [self.view addConstraint:constraint];
    }
    

    就是这样。 IB约束的截图如下:

    【讨论】:

      【解决方案5】:

      感谢 Tark 的回答,我也设法使用了约束:

      1. 将 TobView 的垂直空间约束添加到 Top Layout Guide(使用 StoryBoard)
      2. 将 BottomView 的垂直空间约束添加到 Bottom Layout Guide(使用 StoryBoard)
      3. 为 ViewDidLoad 中的每个视图添加两个高度约束

      代码:

      NSLayoutConstraint *constraint;
      constraint = [NSLayoutConstraint constraintWithItem:_viewTop
                                                attribute:NSLayoutAttributeHeight
                                                relatedBy:NSLayoutRelationEqual
                                                   toItem:self.view
                                                attribute:NSLayoutAttributeHeight
                                               multiplier:0.5
                                                 constant:0];
      
      
      [self.view addConstraint:constraint];
      constraint = [NSLayoutConstraint constraintWithItem:_viewBottom
                                                attribute:NSLayoutAttributeHeight
                                                relatedBy:NSLayoutRelationEqual
                                                   toItem:self.view
                                                attribute:NSLayoutAttributeHeight
                                               multiplier:0.5
                                                 constant:0];
      [self.view addConstraint:constraint];
      

      【讨论】:

        【解决方案6】:

        您可以使用约束来执行此操作(无需代码!)

        1.- 首先创建两个 UIview 并手动将其高度设置为当前设备大小的一半,将一个放在另一个上,就像这样:

        2.- 接下来你必须像这样为它们中的每一个设置约束(这将允许容器填满整个屏幕,一个在另一个之上):

        顶部容器

        底部容器

        3.- 最后,您必须选择两个容器并添加一个新的约束,指定它们将具有相同的高度

        (记得每一步都要clid“添加X约束”)

        现在应该准备好将标签放入每个容器中,您就可以准备好了

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-03
          • 1970-01-01
          • 2011-12-23
          • 2019-11-27
          • 1970-01-01
          • 1970-01-01
          • 2014-07-25
          相关资源
          最近更新 更多