Swift - UIStackView - 如果所有项目的高度都低于阈值则隐藏
Swift - UIStackView - hide if height of all items is below threshold
我有 UIStackView
的垂直模式填充 UIButtons
。我有动态屏幕调整大小,如果堆栈视图中的所有按钮的高度都低于某个阈值,我想隐藏它们。如何自动实现?
我尝试扩展 UIButton
并添加:
override func layoutSubviews() {
super.layoutSubviews()
self.isHidden = (self.frame.height < 20)
}
有效,但是一旦按钮被隐藏,它就永远不会重新出现并且 layoutSubviews
永远不会被回调(即使高度应该再次变大)。
不清楚你在做什么,也不清楚你为什么说设置按钮 .alpha
属性 会有问题,但这里有两种方法,都使用 UIStackView
subclass 并处理 layoutSubviews()
.
中的 show/hide
1: 计算按钮高度 将是 并设置 .isHidden
属性:
class MyStackView: UIStackView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
axis = .vertical
distribution = .fillEqually
spacing = 8
}
override func layoutSubviews() {
super.layoutSubviews()
// approach 1
// setting .isHidden
let numViews = arrangedSubviews.count
let numSpaces = numViews - 1
let h = (bounds.height - (spacing * CGFloat(numSpaces))) / CGFloat(numViews)
let bHide = h < 20
arrangedSubviews.forEach { v in
v.isHidden = bHide
}
}
}
根据按钮高度 设置 .isHidden
属性(更简单):
class MyStackView: UIStackView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
axis = .vertical
distribution = .fillEqually
spacing = 8
}
override func layoutSubviews() {
super.layoutSubviews()
// approach 2
// setting .alpha
arrangedSubviews.forEach { v in
v.alpha = v.frame.height < 20 ? 0.0 : 1.0
}
}
}
这是一个示例控制器,可以看到它的使用情况。点击任意位置将在 300
和 100
之间切换堆栈视图的高度(按钮在 100
处的高度将小于 20 磅):
class ConditionalStackViewController: UIViewController {
let stackView: MyStackView = {
let v = MyStackView()
// so we can see the stack view frame
v.backgroundColor = .systemYellow
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
var stackHeight: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...6 {
let b = UIButton()
b.setTitle("Button \(i)", for: [])
b.setTitleColor(.white, for: .normal)
b.setTitleColor(.lightGray, for: .highlighted)
b.backgroundColor = .red
stackView.addArrangedSubview(b)
}
view.addSubview(stackView)
let g = view.safeAreaLayoutGuide
stackHeight = stackView.heightAnchor.constraint(equalToConstant: 300.0)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
stackHeight,
])
let t = UITapGestureRecognizer(target: self, action: #selector(gotTap(_:)))
view.addGestureRecognizer(t)
}
@objc func gotTap(_ g: UITapGestureRecognizer) -> Void {
stackHeight.constant = stackHeight.constant == 300 ? 100 : 300
}
}
我有 UIStackView
的垂直模式填充 UIButtons
。我有动态屏幕调整大小,如果堆栈视图中的所有按钮的高度都低于某个阈值,我想隐藏它们。如何自动实现?
我尝试扩展 UIButton
并添加:
override func layoutSubviews() {
super.layoutSubviews()
self.isHidden = (self.frame.height < 20)
}
有效,但是一旦按钮被隐藏,它就永远不会重新出现并且 layoutSubviews
永远不会被回调(即使高度应该再次变大)。
不清楚你在做什么,也不清楚你为什么说设置按钮 .alpha
属性 会有问题,但这里有两种方法,都使用 UIStackView
subclass 并处理 layoutSubviews()
.
1: 计算按钮高度 将是 并设置 .isHidden
属性:
class MyStackView: UIStackView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
axis = .vertical
distribution = .fillEqually
spacing = 8
}
override func layoutSubviews() {
super.layoutSubviews()
// approach 1
// setting .isHidden
let numViews = arrangedSubviews.count
let numSpaces = numViews - 1
let h = (bounds.height - (spacing * CGFloat(numSpaces))) / CGFloat(numViews)
let bHide = h < 20
arrangedSubviews.forEach { v in
v.isHidden = bHide
}
}
}
根据按钮高度 设置
.isHidden
属性(更简单):class MyStackView: UIStackView {
override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init(coder: NSCoder) { super.init(coder: coder) commonInit() } func commonInit() -> Void { axis = .vertical distribution = .fillEqually spacing = 8 } override func layoutSubviews() { super.layoutSubviews() // approach 2 // setting .alpha arrangedSubviews.forEach { v in v.alpha = v.frame.height < 20 ? 0.0 : 1.0 } }
}
这是一个示例控制器,可以看到它的使用情况。点击任意位置将在 300
和 100
之间切换堆栈视图的高度(按钮在 100
处的高度将小于 20 磅):
class ConditionalStackViewController: UIViewController {
let stackView: MyStackView = {
let v = MyStackView()
// so we can see the stack view frame
v.backgroundColor = .systemYellow
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
var stackHeight: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...6 {
let b = UIButton()
b.setTitle("Button \(i)", for: [])
b.setTitleColor(.white, for: .normal)
b.setTitleColor(.lightGray, for: .highlighted)
b.backgroundColor = .red
stackView.addArrangedSubview(b)
}
view.addSubview(stackView)
let g = view.safeAreaLayoutGuide
stackHeight = stackView.heightAnchor.constraint(equalToConstant: 300.0)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
stackHeight,
])
let t = UITapGestureRecognizer(target: self, action: #selector(gotTap(_:)))
view.addGestureRecognizer(t)
}
@objc func gotTap(_ g: UITapGestureRecognizer) -> Void {
stackHeight.constant = stackHeight.constant == 300 ? 100 : 300
}
}