Swift iOS中使用Trait Collection的自适应布局

时间:2018-01-11 12:55:28

标签: ios swift autolayout

当设备处于纵向模式时,我尝试将屏幕上的UIView布局在16:9的宽高比位于顶部,并且当设备处于横向模式时,我将尝试全屏显示(如视频播放器屏幕)。我决定使用大小类。这是我如何实现它,但我对实现不满意,并且存在一些错误。这是我的代码:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    if traitCollection.verticalSizeClass == .compact {
        localPlayerView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

    } 
}

override func viewWillLayoutSubviews() {
    if traitCollection.verticalSizeClass == .compact {
        localPlayerView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

    }

    if traitCollection.horizontalSizeClass == .compact {
        localPlayerView.removeFromSuperview()

        view.addSubview(localPlayerView)

        let height = view.frame.width * 9 / 16
        localPlayerView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: height)
        collectionView.anchor(top: localPlayerView.bottomAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

        localPlayerView.layoutIfNeeded()
    }
}

我不得不从superview中删除localPlayerView并将其添加回来以获得所需的结果,因为当我切换回肖像时,它仍然限制为完整的超视图宽度。 如何改进此代码以获得相同的结果?

1 个答案:

答案 0 :(得分:1)

每当您给出定义其大小和位置的localPlayerView个新约束时,您必须删除/停用旧约束。在你的代码中,似乎你总是只是添加新的约束,这将导致不可满足的约束,然后布局出现问题 - 更重要的是,如果你从superview中删除播放器然后再添加它,那将删除那些约束 - 只有证实了我的假设。你必须小心,始终有非冲突的约束。

如何做到这一点只是一个广泛的指导方针。在viewController中定义两个属性:

var portraitConstraints: [NSLayoutConstraint] = []
var landscapeConstraints: [NSLayoutConstraint] = []

然后,一旦加载了视图(例如,在viewDidLoad中),就相应地填充它们:

portraitConstraints = [ 
    // here create all the constraints that are needed to properly define position and size of the player when in portrait
]
landscapeConstraints = [ 
    // all the constraints for landscape
]
NSLayoutConstraint.activate(portraitConstraints) // activate these as default

然后在traitCollectionDidChange检测你是在横向还是纵向(我省略了这个代码,你可以找到关于那个的SO问题),并且只是激活适当的约束(并停用旧约束):

let inLandscape = // code to detect current orientation
if inLandscape {
    NSLayoutConstraint.deactivate(portraitConstraints)
    NSLayoutConstraint.activate(landscapeConstraints)
} else {
    NSLayoutConstraint.deactivate(landscapeConstraints)
    NSLayoutConstraint.activate(portraitConstraints)
}