【问题标题】:constraints reverting back to original position when width is increased当宽度增加时约束恢复到原始位置
【发布时间】:2021-08-23 06:42:38
【问题描述】:

滑块将对象的位置更改为其原始位置。你可以在下面的 gif 中看到白人。我只想在用户更改对象的大小时保持在其原始位置而不恢复到其原始位置。我想这一切都受到了 var backCon 的影响。

import UIKit

class ViewController: UIViewController {
    
    var backBox = UIButton()
    
    
    var slider = UISlider()
    
    var panGesture = UIPanGestureRecognizer()
    var backCon = [NSLayoutConstraint]()
    
    var widthConstraints: NSLayoutConstraint?
    
    var tim = 50.0
    var slidermultiplier: CGFloat = 0.6
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [backBox,slider].forEach{
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
            $0.backgroundColor = UIColor(
                red: .random(in: 0.0...1),
                green: .random(in: 0.9...1),
                blue: .random(in: 0.7...1),
                alpha: 1
            )
            
        }
        
        NSLayoutConstraint.activate([
            slider.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            slider.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            slider.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.1),
            slider.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
            
        ])
        
        widthConstraints = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
        
        backCon = [
            backBox.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            
            backBox.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: CGFloat(tim)),
            backBox.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.5),
            widthConstraints!,
            
        ]
        
        panGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.draggedView(_:)))
        
        NSLayoutConstraint.activate(backCon)
        
        backBox.isUserInteractionEnabled = true
        
        slider.addTarget(self, action: #selector(increase), for: .valueChanged)
        
        backBox.addGestureRecognizer(panGesture)
        
    }
    
    @objc func increase() {
        
        slidermultiplier = CGFloat(slider.value)
        widthConstraints?.isActive = false
        widthConstraints = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
        widthConstraints?.isActive = true
    }
    
    @objc func draggedView(_ sender: UIPanGestureRecognizer) {
        
        let translation = sender.translation(in: self.view)
        backBox.center = CGPoint(x: backBox.center.x + translation.x , y: backBox.center.y + translation.y)
        
        sender.setTranslation(CGPoint.zero, in: self.view)
        
    }
    
    @objc func sliderr() {
        
        NSLayoutConstraint.deactivate(backCon)
        
        backCon = [
            
            backBox.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            
            backBox.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: CGFloat(-tim)),
            backBox.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
            widthConstraints!,
        ]
        
        NSLayoutConstraint.activate(backCon)
        
    }
    
}

【问题讨论】:

    标签: slider constraints var nslayoutconstraint


    【解决方案1】:

    在使用自动布局约束,然后显式设置帧值(包括.center)时,您几乎总是会遇到问题。

    因此,就像您对宽度约束所做的那样,您需要为Leading 和CenterY 创建约束,这样您就可以更新它们而不是设置.center =

    @objc func draggedView(_ sender: UIPanGestureRecognizer) {
        
        let translation = sender.translation(in: self.view)
        
        // update backBox Leading and CenterY constraints
        backBoxLeading.constant += translation.x
        backBoxCenterY.constant += translation.y
        
        sender.setTranslation(CGPoint.zero, in: self.view)
        
    }
    

    这是一个完整的实现(修改您的代码)。 // cmets 应该很清楚:

    class SamViewController: UIViewController {
        
        var backBox = UIButton()
        
        var slider = UISlider()
        
        var panGesture = UIPanGestureRecognizer()
    
        // constraint we will modify when slider is changed
        var backBoxWidth: NSLayoutConstraint!
    
        // constraints we will modify when backBox is dragged
        var backBoxCenterY: NSLayoutConstraint!
        var backBoxLeading: NSLayoutConstraint!
        
        var tim = 50.0
        var slidermultiplier: CGFloat = 0.6
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            [backBox,slider].forEach{
                $0.translatesAutoresizingMaskIntoConstraints = false
                view.addSubview($0)
                $0.backgroundColor = UIColor(
                    red: .random(in: 0.0...1),
                    green: .random(in: 0.9...1),
                    blue: .random(in: 0.7...1),
                    alpha: 1
                )
            }
            
            NSLayoutConstraint.activate([
                slider.bottomAnchor.constraint(equalTo: view.bottomAnchor),
                slider.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                slider.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.1),
                slider.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
                
            ])
    
            // backBox Width constraint
            backBoxWidth = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
            
            // backBox CenterY constraint
            backBoxCenterY = backBox.centerYAnchor.constraint(equalTo: view.centerYAnchor)
            
            // backBox Leading constraint
            backBoxLeading = backBox.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: CGFloat(tim))
            
            NSLayoutConstraint.activate([
    
                // backBox Height is constant
                backBox.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.5),
                
                backBoxWidth,
                backBoxLeading,
                backBoxCenterY,
                
            ])
            
            panGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedView(_:)))
            
            backBox.isUserInteractionEnabled = true
            
            slider.addTarget(self, action: #selector(increase), for: .valueChanged)
            
            backBox.addGestureRecognizer(panGesture)
            
            // we start the backBox Width at "slidermultiplier" of view, so
            //  start the slider at "slidermultiplier"
            slider.setValue(Float(slidermultiplier), animated: false)
            
        }
        
        @objc func increase() {
            
            slidermultiplier = CGFloat(slider.value)
    
            // update backBox Width constraint
            backBoxWidth.isActive = false
            backBoxWidth = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
            backBoxWidth.isActive = true
            
        }
        
        @objc func draggedView(_ sender: UIPanGestureRecognizer) {
            
            let translation = sender.translation(in: self.view)
            
            // update backBox Leading and CenterY constraints
            backBoxLeading.constant += translation.x
            backBoxCenterY.constant += translation.y
            
            sender.setTranslation(CGPoint.zero, in: self.view)
            
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-14
      • 1970-01-01
      • 2013-10-02
      • 1970-01-01
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 2017-02-26
      相关资源
      最近更新 更多