当宽度增加时约束恢复到原来的位置

constraints reverting back to original position when width is increased

滑块将对象的位置更改为其原始位置。您可以在下面的 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{
            [=10=].translatesAutoresizingMaskIntoConstraints = false
            view.addSubview([=10=])
            [=10=].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)
        
    }
    
}

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

所以,就像您对 Width 约束所做的那样,您需要为 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)
    
}

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

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{
            [=11=].translatesAutoresizingMaskIntoConstraints = false
            view.addSubview([=11=])
            [=11=].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)
        
    }

}