ios - 在实际旋转之前确定导航栏的新框架 - iOS

标签 ios cocoa-touch user-interface uiinterfaceorientation nslayoutconstraint

我正在使用半透明的导航栏和状态栏,我的 View Controller 需要全屏显示。因此,我的 View Controller 的 View 在 Nav 和 Status 栏下延伸并占据了整个屏幕。

我还有一个标签,我想将其直接对齐到导航栏下方。因为我不能直接在标签和导航栏之间添加约束,所以我在标签的顶部和它的父 View 的顶部之间添加了我的约束。我将约束的常量设置为等于状态栏的高度 + 导航栏的高度。

我遇到的问题是在纵向和横向之间旋转期间,因为导航栏的高度发生了变化,我需要我的标签也能很好地旋转,所以我需要知道 中导航栏的新高度>willRotateToInterfaceOrientation: 方法。

当 View Controller 从纵向或横向导航到时,我使用此方法确保标签位于正确的位置。它工作正常。

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Get Y origin for Label
    CGFloat navBarY = self.navigationController.navigationBar.frame.origin.y;
    CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
    CGFloat labelY = navBarY + navBarHeight;

    // Set vertical space constraint for Label
    self.labelConstraint.constant = labelY;
}

当导航栏高度从 44 像素变为 32 像素时,我使用此方法在方向更改时重新定位标签。问题是,在旋转实际发生之前,我需要获得导航栏在旋转后的新高度。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    // Get Y origin for Label
    CGFloat navBarY = self.navigationController.navigationBar.frame.origin.y;
    CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
    CGFloat labelY = navBarY + navBarHeight;


    // This obviously returns the the current Y origin for label before the rotation
    // Which isn't very useful.

    NSLog(@"labelY: %f", labelY);


    // This code produces the desired effect, but obviously I want to avoid
    // hard-coding the values.

    if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
        self.labelConstraint.constant = 20 + 32;
    } else {
        self.labelConstraint.constant = 20 + 44;
    }
} 

为了好玩,我尝试在 didRotateFromInterfaceOrientation: 中设置旋转后标签的 Y 原点,但正如预期的那样,它并不平滑,并且标签在旋转完成后卡入到位。

预先感谢您的协助!

最佳答案

答案是:Size Classes。您可以自行了解它,Apple 对此进行了详细记录。您将不得不使用此函数:func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)。设置 View 时,我建议在 View Controller 中添加两个属性,都是 NSLayoutConstraint 数组,一个用于纵向模式,一个用于横向。从 iOS 8 开始,可以同时激活/停用多个约束。在上述函数中,执行以下操作:

if newCollection.verticalSizeClass == .Compact { //orientiation is landscape
    NSLayoutConstraint.deactivateConstraints(self.portraitConstraints)
    NSLayoutConstraint.activateConstraints(self.landscapeConstraints)
} else {
    NSLayoutConstraint.deactivateConstraints(self.landscapeConstraints)
    NSLayoutConstraint.activateConstraints(self.portraitConstraints)
}

确保先停用,否则您的约束会发生冲突。

对于“迅速”的回答,我深表歉意,我想您可以将其“翻译”成 ObjC。如果您有任何问题,请随时提出。

关于ios - 在实际旋转之前确定导航栏的新框架 - iOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17765960/

相关文章:

ios - 每个部分可以选择的项目数量限制

java - 如何手动移动 GUI 元素?

objective-c - 在 UILabel 或 TextView 中显示垂直小数

iphone - 如何关闭 UIWebView 上的键盘?

ios - 测量蜂窝信号强度

python - 如何处理多个通用用户界面?

html - Bootstrap 3 网格行跨度

ios - Xcode 有什么方法可以提高音频播放质量吗?

ios - 通过核心数据查询最大值、最小值和其他

ios - 在 UIButton 的文本周围添加边框