【问题标题】:Updating variable in view constraint (SnapKit)更新视图约束中的变量(SnapKit)
【发布时间】:2021-08-17 06:30:45
【问题描述】:

使用以下约束初始化视图


  View.snp.makeConstraints { (para) in
       View.topConstraint = para.top.equalTo(parentview.snp.top).constraint
       View.LeadingConstraint = para.leading.equalTo(parentview.snp.leading).constraint
       View.TrailingConstraint = para.trailing.equalTo(parentview.snp.trailing).constraint
       View.BottomConstraint =para.bottom.equalTo(parentview.snp.bottom).offset(-getheight).constraint
        
  }

其中 getheight = parentview.frame.size.height/2 ;

当父视图更改其尺寸时。视图不会更新其高度,因为不会再次调用约束。 任何更新或召回其约束的方式,而不是在大规模上不可行的 remakingConstraint。 试过了:

View.updateConstraints()
View.setNeedsUpdateConstraints()
View.setNeedsLayout()

我需要参考每个约束,因为

if View.bottomTouch {
      View.bottomConstraint.update(offset: View. BottomConstraint.layoutConstraints[0].constant + CurrentPoint - PreviousPoint)
}

【问题讨论】:

    标签: swift autolayout snapkit


    【解决方案1】:

    您是否有不想使用 50% 的父视图高度的原因?

        View.snp.makeConstraints { (para) in
            para.top.equalTo(parentview.snp.top)
            para.leading.equalTo(parentview.snp.leading)
            para.trailing.equalTo(parentview.snp.trailing)
    
            // 50% of the parent view height
            para.height.equalTo(parentview.snp.height).multipliedBy(0.5)
    
            // instead of this
            //para.bottom.equalTo(parentview.snp.bottom).offset(-getheight)
        }
    

    编辑 - 在 cmets...

    为了拖动视图而保留对约束的引用与“将子视图保持在父视图高度的 50%”是一个非常不同的问题。

    试试这个...

    它将创建一个cyan“parentView”和一个blue“childView”(子视图)。 拖动蓝色视图(平移手势)将向上/向下拖动其底部。点击任意位置(点击手势)将在 20 到 60 之间切换 parentView 框架上的插图。

    当 parentView 框架发生变化时——无论是通过点击还是在设备旋转时——“childView”底部将重置为“parentView”高度的 50%:

    class ViewController: UIViewController {
    
        let parentView = UIView()
        let childView = UIView()
        
        // childView bottom constraint
        var bc: Constraint!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            parentView.backgroundColor = .cyan
            childView.backgroundColor = .blue
            
            parentView.addSubview(childView)
            view.addSubview(parentView)
            
            parentView.snp.makeConstraints { para in
                para.top.leading.trailing.bottom.equalTo(self.view.safeAreaLayoutGuide).inset(20.0)
            }
            
            // childView's bottom constraint offset will be set in viewDidLayoutSubviews()
            childView.snp.makeConstraints { para in
                para.top.leading.trailing.equalToSuperview()
                bc = para.bottom.equalToSuperview().constraint
            }
            
            let p = UIPanGestureRecognizer(target: self, action: #selector(panHandler(_:)))
            childView.addGestureRecognizer(p)
            
            let t = UITapGestureRecognizer(target: self, action: #selector(tapHandler(_:)))
            view.addGestureRecognizer(t)
        }
    
        @objc func tapHandler(_ g: UITapGestureRecognizer) -> Void {
            
            // on tap, toggle parentView inset
            //  between 20 and 60
            // this will trigger viewDidLayoutSubviews(), where the childView bottom
            //  constraint will be reset to 50% of the parentView height
            var i: CGFloat = 60.0
            if parentView.frame.origin.x > 20 {
                i = 20.0
            }
            parentView.snp.updateConstraints { para in
                para.top.leading.trailing.bottom.equalTo(self.view.safeAreaLayoutGuide).inset(i)
            }
            
        }
    
        @objc func panHandler(_ g: UIPanGestureRecognizer) -> Void {
            
            let translation = g.translation(in: g.view)
    
            // update bottom constraint constant
            bc.layoutConstraints[0].constant += translation.y
            
            // reset gesture translation
            g.setTranslation(CGPoint.zero, in: self.view)
    
        }
        
        var parentViewHeight: CGFloat = 0.0
        
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            
            // reset childView's bottom constraint
            //  to 50% of its superView's height
            //  ONLY if parentView frame height has changed
            if parentView.frame.height != parentViewHeight {
                parentViewHeight = parentView.frame.height
                bc.layoutConstraints[0].constant = -parentViewHeight * 0.5
            }
            
        }
        
    }
    

    【讨论】:

    • 非常尊重!写了超过 3k 行约束而没有考虑这一点。我使用的是顶部底部前导尾随,因为我也在保存这些约束以供以后更改,但我找不到方法。
    • self.View.bottomConstraint = para.bottom.equalTo(parentview.snp.bottom).offset(-getheight).constraint 现在是额外的。有什么办法可以参考它。因为我需要它。
    • @Divine - 我认为你需要解释为什么你需要那个。
    • 计算可能的第一次触摸偏移量。
    • @Divine - 嗯?我希望你在触摸时检查框架......我想不出你会对约束做任何事情的情况。
    【解决方案2】:

    首先,检查getheight 值是否在父视图布局更改时更新。为了重新加载现有约束,您可能需要调用父视图的layoutIfNeeded()

    【讨论】:

    • 一切都很好。如果我手动调用我的约束,那么它会得到纠正。我要求我可以使用任何方法来更新或刷新我的约束。
    猜你喜欢
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多