【问题标题】:UIStackView's subviews have intrinsic size, yet still ignore content hugging prioritiesUIStackView 的子视图具有固有大小,但仍然忽略包含优先级的内容
【发布时间】:2020-07-09 22:40:16
【问题描述】:

我正在尝试以编程方式创建一个具有填充分布的堆栈视图,允许我选择拉伸哪些子视图以填充额外空间,但到目前为止我似乎无法控制哪个视图正在扩展。

class ShelfVC: UIViewController {

    let shelfContentView = UIStackView()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(shelfContentView)
        shelfContentView.translatesAutoresizingMaskIntoConstraints = false
        shelfContentView.layoutEqualTo(view: view)
        shelfContentView.spacing = 16

        shelfContentView.isLayoutMarginsRelativeArrangement = true
        let shelfMargin = CGFloat(16)
        shelfContentView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: shelfMargin, leading: shelfMargin, bottom: shelfMargin, trailing: shelfMargin)
        
        createTestBlocks()
    }

    func createTestBlocks() {

            let view1 = UIView()
            shelfContentView.addArrangedSubview(view1)
            view1.widthAnchor.constraint(equalToConstant: 100).isActive = true
            view1.backgroundColor = .systemRed
            view1.setContentHuggingPriority(.defaultHigh, for: .horizontal)

            let view2 = UIView()
            shelfContentView.addArrangedSubview(view2)
            view2.widthAnchor.constraint(equalToConstant: 100).isActive = true
            view2.backgroundColor = .systemPurple
            view2.setContentHuggingPriority(.defaultLow, for: .horizontal)
            
            let view3 = UIView( )
            shelfContentView.addArrangedSubview(view3)
            view3.widthAnchor.constraint(equalToConstant: 100).isActive = true
            view3.backgroundColor = .systemBlue
            view3.setContentHuggingPriority(.defaultHigh, for: .horizontal)
    }
}

我期待看到这个:

但是,相反,我看到了:

为什么蓝色视图的拥抱优先级高于紫色视图时会拉伸?

【问题讨论】:

    标签: ios swift layout autolayout uistackview


    【解决方案1】:

    Content Hugging Priority 与 Constraint Priority 不同,且 Constraints 不定义 Intrinsic Content Size。

    内容拥抱(和内容压缩阻力)优先级基于内在内容大小。

    您已经给每个视图一个 Width 约束,而您的堆栈视图正在使用它来开始 安排。然后它打破其中一个约束,因为它不能满足所有约束。

    你有两个选择:

    • 约束不同的优先级
    • 给视图一个固有内容大小并设置拥抱优先级

    这是第一个例子:

    class ConstraintHuggingShelfVC: UIViewController {
        
        let shelfContentView = UIStackView()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            view.addSubview(shelfContentView)
            shelfContentView.translatesAutoresizingMaskIntoConstraints = false
            
            NSLayoutConstraint.activate([
                
                shelfContentView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0),
                shelfContentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0),
                shelfContentView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0),
                shelfContentView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0),
                
            ])
            
            //shelfContentView.layoutEqualTo(view: view)
            shelfContentView.spacing = 16
            
            shelfContentView.isLayoutMarginsRelativeArrangement = true
            let shelfMargin = CGFloat(16)
            shelfContentView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: shelfMargin, leading: shelfMargin, bottom: shelfMargin, trailing: shelfMargin)
            
            createTestBlocks()
        }
        
        func createTestBlocks() {
            
            let view1 = UIView()
            shelfContentView.addArrangedSubview(view1)
            view1.backgroundColor = .systemRed
    
            let wc1 = view1.widthAnchor.constraint(equalToConstant: 100)
            wc1.isActive = true
            wc1.priority = .defaultHigh
    
            let view2 = UIView()
            shelfContentView.addArrangedSubview(view2)
            view2.backgroundColor = .systemPurple
    
            let wc2 = view2.widthAnchor.constraint(equalToConstant: 100)
            wc2.isActive = true
            wc2.priority = .defaultLow
    
            let view3 = UIView( )
            shelfContentView.addArrangedSubview(view3)
            view3.backgroundColor = .systemBlue
            
            let wc3 = view3.widthAnchor.constraint(equalToConstant: 100)
            wc3.isActive = true
            wc3.priority = .defaultHigh
            
        }
    }
    

    这是第二个例子:

    class IntrinsicView: UIView {
        var myIntrinsicSize: CGSize = .zero
        override var intrinsicContentSize: CGSize {
            return myIntrinsicSize
        }
    }
    
    class IntrisicSizeShelfVC: UIViewController {
        
        let shelfContentView = UIStackView()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            view.addSubview(shelfContentView)
            shelfContentView.translatesAutoresizingMaskIntoConstraints = false
            
            NSLayoutConstraint.activate([
                
                shelfContentView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0),
                shelfContentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0),
                shelfContentView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0),
                shelfContentView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0),
                
            ])
    
    //      shelfContentView.layoutEqualTo(view: view)
            shelfContentView.spacing = 16
            
            shelfContentView.isLayoutMarginsRelativeArrangement = true
            let shelfMargin = CGFloat(16)
            shelfContentView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: shelfMargin, leading: shelfMargin, bottom: shelfMargin, trailing: shelfMargin)
            
            createTestBlocks()
        }
        
        func createTestBlocks() {
            
            let view1 = IntrinsicView()
            shelfContentView.addArrangedSubview(view1)
            view1.backgroundColor = .systemRed
    
            view1.myIntrinsicSize = CGSize(width: 100, height: 0)
            view1.setContentHuggingPriority(.defaultHigh, for: .horizontal)
            
            let view2 = IntrinsicView()
            shelfContentView.addArrangedSubview(view2)
            view2.backgroundColor = .systemPurple
    
            view2.myIntrinsicSize = CGSize(width: 100, height: 0)
            view2.setContentHuggingPriority(.defaultLow, for: .horizontal)
            
            let view3 = IntrinsicView( )
            shelfContentView.addArrangedSubview(view3)
            view3.backgroundColor = .systemBlue
    
            view3.myIntrinsicSize = CGSize(width: 100, height: 0)
            view3.setContentHuggingPriority(.defaultHigh, for: .horizontal)
        }
    }
    

    两者都产生相同的布局:

    【讨论】:

      【解决方案2】:

      UIStackView 根据内容压缩优先级使用.fill 收缩和扩展,如果排列的子视图没有填满堆栈视图。因此,请尝试将 setContentHuggingPriority 更改为 setContentCompressionResistancePriority

      有关UIStackView.Distribution.fill 属性的更多信息,请参阅https://developer.apple.com/documentation/uikit/uistackview/distribution/fill

      【讨论】:

      • 您的意思是尝试将setContentHuggingPriority 更改为setContentCompressionResistancePriority
      猜你喜欢
      • 1970-01-01
      • 2021-08-28
      • 2019-02-06
      • 2018-10-27
      • 2019-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多