【问题标题】:Where to change "installed" for Auto Layout constraint?在哪里更改自动布局约束的“已安装”?
【发布时间】:2023-03-08 08:27:01
【问题描述】:

在情节提要中使用自动布局时,可以使用“已安装”复选框来选择是否安装约束。禁用它会导致它的行为就像您没有添加该约束一样 - 它不会产生任何影响。您可以在 Interface Builder 中为不同大小的类配置已安装状态,您可以通过将其 active 属性设置为 truefalse 以编程方式更改此值。

在我的应用程序中,我希望仅在设备处于纵向时安装约束 - 旋转到横向时应该“卸载”。这可以通过取消选中已安装的任何宽度紧凑高度来为 iPhone 完成。 (尽管这似乎不太正确,因为它在旋转到横向时甚至不应该安装时由于冲突的约束而打破了这个约束,但不管 UI 总是按预期显示。)但是没有办法卸载Interface Builder 中 iPad 的横向约束(两个方向的常规宽度常规高度)。

在旋转设备时启用/禁用 activeNSLayoutConstraints 的正确位置在哪里? 以何种旋转方法更改该状态会导致所需的行为 - 仅安装用于肖像?如果在应用启动时没有调用该方法,除了轮换方法之外,还应该将它放在什么其他方法中?

我已尝试将以下代码放在 viewDidLoadviewWillTransitionToSize 中,但这会导致在 iPad 上运行时出现一些意外行为:

  • 在横向启动应用程序会导致约束处于活动状态,尽管 active 设置为 false,它会破坏约束,并且 UI 不会按预期显示
  • 纵向启动应用程序将 active 设置为 true(它已安装在 IB 中),因此它可以按预期工作
  • 纵向启动应用程序并将设备旋转到横向按预期工作 - 约束设置为非活动,它不会破坏约束,UI 显示如预期
  • 以纵向启动应用程序、旋转到横向并返回到纵向会导致 UI 显示正确,但它会打破设置为活动的限制

如果我在 Interface Builder 中卸载约束,然后运行上述场景,我会得到基本上相反的行为。

if size.width > size.height {
    self.myConstraint.active = false
} else {
    self.myConstraint.active = true
}

【问题讨论】:

    标签: ios ios8 screen-rotation autolayout


    【解决方案1】:

    我回答得有点晚了,但是当我遇到类似的问题来解决 Autolayout 无法检测 iOS 7 的 iPhone 的紧凑宽度/紧凑高度的问题时,这是我的 2 美分。 iOS 7 中没有 activated 属性,所以我不得不添加/删除它们。

    我创建了两种方法来添加和删除约束,这些约束已经在 IB 上设置,我使用 IBOutlet 属性引用它们。因此,由于我删除了它们,与其他 IB 对象不同,我应该将它们设置为 strong,而不是 weak。否则,一旦我删除它们,它们就会被销毁,我将无法再次引用它们来重新添加它们。

    这是我的约束移除方法:

    -(void)removeiOS7andiPhone4inLandscapeToOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    
        if( !UIInterfaceOrientationIsLandscape(toInterfaceOrientation )&&(NSFoundationVersionNumber<=NSFoundationVersionNumber_iOS_7_1)&&( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone )){
             // if iPhone with iOS 7 on portrait remove Constraints here
    
        }
    }
    

    这里是约束加法器方法:

    -(void)addiOS7andiPhone4inLandscapeToOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    
        if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation )&&(NSFoundationVersionNumber<=NSFoundationVersionNumber_iOS_7_1)&&( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone )){
           // if iPhone with iOS 7 on landscape add Constraints here
    
        }
    
    }
    

    至于在哪里调用这些方法,正如你所尝试的那样,在viewWillAppear(无需调用viewWillDisappear)和viewWillTransitionToSize(在我的情况下这是willRotateToInterfaceOrientation,因为@987654330 @ 仅在 iOS 8) 之后可用。随后调用它们是有道理的,毕竟在进行必要的更改之前,由于使用if 检查它们的纵向/横向方向,因此只会运行它们中的一个。

    这是我的willRotateToInterfaceOrientation 方法定义:

    -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    
        // this will be run only if orientation is on Portrait
        [self addiOS7andiPhone4inLandscapeToOrientation:toInterfaceOrientation];
    
        // this will be run only if orientation is on Landscape
        [self removeiOS7andiPhone4inLandscapeToOrientation:toInterfaceOrientation];
    }
    

    并在viewWillAppear 中拨打类似电话。

    注意:确保您在这些方法中执行完全相反的操作,并且您不一定只在 addConstraintMethod 中添加约束并仅在 removeConstraintMethod 中删除。在我的例子中,我在每个方法中都添加和删除了约束,所以方法的命名并不能准确地反映它们的真实作用,但只要你做的完全相反,你就可以了。

    【讨论】:

      【解决方案2】:

      理想情况下我会使用这些方法,但它们的缺点是它们只会在发生变化时通知控制器。

      /* 
       This method is called when the view controller's view's size is changed by its parent (i.e. for the root view controller when its window rotates or is resized). 
      
       If you override this method, you should either call super to propagate the change to children or manually forward the change to children.
       */
      - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);
      
      /* 
       This method is called when the view controller's trait collection is changed by its parent.
      
       If you override this method, you should either call super to propagate the change to children or manually forward the change to children.
       */
      - (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);
      

      我更喜欢在初始和方向更改时对约束进行自定义,

      - (void)updateViewConstraints NS_AVAILABLE_IOS(6_0);
      

      【讨论】:

        猜你喜欢
        • 2014-09-03
        • 1970-01-01
        • 1970-01-01
        • 2016-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-31
        相关资源
        最近更新 更多