我想根据设备方向更改按钮高度限制。我正在创建高度限制。然后我为风景模式设置了高度限制60,为人像模式设置了40。但是当我更改设备方向时,高度不会变大。问题出在哪儿。这是我的代码
lazy var nextEpisodeButton: CustomPlayerButton = {
let nextEpisode = CustomPlayerButton(type: .nextEpisode, backgroundImage: nil)
nextEpisode.addTarget(self, action: #selector(nextEpisodeTapped), for: .touchUpInside)
nextEpisode.translatesAutoresizingMaskIntoConstraints = false
nextEpisode.adjustsImageWhenHighlighted = false
return nextEpisode
}()
func addNextEpisodeButton() {
view.addSubview(nextEpisodeButton)
NSLayoutConstraint.activate([
nextEpisodeButton.heightAnchor.constraint(equalToConstant: 40),
nextEpisodeButton.widthAnchor.constraint(equalToConstant: 120),
nextEpisodeButton.rightAnchor.constraint(equalTo: view.safeRightAnchor, constant: -20),
nextEpisodeButton.bottomAnchor.constraint(equalTo: view.safeBottomAnchor, constant: -60)
])
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: size, with: coordinator)
if UIDevice.current.orientation.isLandscape {
nextEpisodeButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
} else {
nextEpisodeButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
}
nextEpisodeButton.layoutIfNeeded()
}
答案 0 :(得分:0)
您应该在ViewController中的某个地方引用nextEpisodeButton.heightAnchor.constraint(equalToConstant: 40)
约束,而在willTransition
回调中只需更改其constant
值即可。使用您的代码,您可以在每次旋转时创建并激活一个新约束,而不是更改现有约束。
答案 1 :(得分:0)
约束是持久的。当您为同一属性(在您的情况下为视图的高度)创建第二个约束并激活该约束时,这两个约束相互冲突。
因此,您需要为它们两个都保留一个引用,并相应地激活/停用它们:
'demo
Cells.Clear
bigno = 12345
For i = 1 To 20
Cells(i, 1) = bigno
If Rnd > 0.8 Then bigno = bigno + Int(Rnd * 10000) + 10000
Next i
'code
usn = 1
Cells(1, 2) = usn
For i = 2 To 20
If Cells(i, 1) <> Cells(i - 1, 1) Then usn = usn + 1
Cells(i, 2) = usn
Next i
答案 2 :(得分:0)
我的方法是做两件事:
让我们从第一个开始。您将有一个良好的开端-约束是(a)代码中的约束和(b)使用锚点的约束。 (如果您偶然使用IB-其他的故事板,则需要将更改的约束设置为@IBOutlets
。)
您似乎希望此按钮位于右下角,因此让这些约束处于活动状态:
nextEpisodeButton.rightAnchor.constraint(equalTo: view.safeRightAnchor, constant: -20).isActive = true
nextEpisodeButton.bottomAnchor.constraint(equalTo: view.safeBottomAnchor, constant: -60).isActive = true
无论方向如何,这都会正确地固定东西。
现在,假设您要更改尺寸。您需要将它们放入两个数组:
var portraitLayout = [NSLayoutConstraint]()
var landscapeLayout = [NSLayoutConstraint]()
portraitLayout.append(nextEpisodeButton.widthAnchor.constraint(equalToConstant: 120))
portraitLayout.append(nextEpisodeButton.heightAnchor.constraint(equalToConstant: 40))
landscapeLayout.append(nextEpisodeButton.widthAnchor.constraint(equalToConstant: 120))
landscapeLayout.append(nextEpisodeButton.heightAnchor.constraint(equalToConstant: 60))
这将在纵向中设置40x120按钮,在横向中设置60x120按钮。可以(应该?)在viewDidLoad
中完成。现在该激活/停用了。...
仅一个数组应该处于活动状态,并且在初始化视图时需要执行一个操作。我会讲到的,但首先,让我显示两行必要的代码:
NSLayoutConstraint.deactivate(landscapeLayout)
NSLayoutConstraint.activate(portraitLayout)
您可以尝试添加/删除约束,但这不仅冒险,而且不那么容易维护,甚至不需要。只需将所有约束设置为常数isActive = true
,将要更改的约束放入数组,然后激活/停用。
(如果您想为这样的更改添加动画效果-我不希望您这样做-然后执行此操作并在末尾添加UIView.animate(withDuration:)
。)
现在,粗糙的工件正在检测方向。
苹果几年前决定添加特征集。他们运作良好(今年,我终于明白了为什么他们会像以前那样做)。但是它们有一个严重的问题-全屏模式iPad总是具有正常大小。 (我今年正在编写一个仅限iPad的应用,在分屏模式下,它可能非常紧凑。)
您的问题强调方向,所以我建议不使用特征收集更改。而是使用viewWillLayoutSubviews
。对我来说,这似乎更可靠-这是我发现的最早的视图控制器生命周期。您需要做两件事...设置初始方向并检测更改。
这是我的设置。在UIView
扩展名中:
public func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool {
if self.frame.width > self.frame.height {
if isInPortrait {
isInPortrait = false
return true
}
} else {
if !isInPortrait {
isInPortrait = true
return true
}
}
return false
}
public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) {
NSLayoutConstraint.deactivate(l)
NSLayoutConstraint.deactivate(p)
if self.bounds.width > self.bounds.height {
NSLayoutConstraint.activate(l)
} else {
NSLayoutConstraint.activate(p)
}
}
p
和l
分别是纵向和横向。我要做的只是简单地检查界限,并适当地启用/停用。
override func viewWillLayoutSubviews() {
super.viewDidLayoutSubviews()
if initialOrientation {
initialOrientation = false
if view.frame.width > view.frame.height {
isInPortrait = false
} else {
isInPortrait = true
}
view.setOrientation(p, l)
} else {
if view.orientationHasChanged(&isInPortrait) {
view.setOrientation(p, l)
}
}
}
这可能满足您的需求。我基本上是在跟踪两件事(初始方向和当前方向)以进行更改,并在需要时调用它们-viewWillLayoutSubviews
在load(?)期间可以被多次调用,并且除方向改变之外还可以出于其他原因。
结论:
您很亲密,但有一些更改。首先,将常量约束设置为isActive = true
,然后将其余约束作为数组激活/去激活。其次,除非您的应用程序仅是iPhone(即使那时它仍然可以在iPad上使用),否则请不要使用特征收集,而应使用视图控制器生命周期和屏幕边界。