导致初始化约束被还原的滑块

slider causing initialized constraints to be reverted

当我使用滑块时,它会恢复到原来的位置。我不知道 increase func 中发生了什么导致这样做。我想在我不想删除的代码中保留初始化约束。我只想在用户更改对象的滑块值时不恢复到原始位置。你可以在 gif 中看到发生了什么。

import UIKit

class ViewController: UIViewController {
    
    var slizer = UISlider()
    var oldCons = [NSLayoutConstraint]()
    var viewDrag = UIImageView()
    var panGesture = UIPanGestureRecognizer()
    
    var widthConstraints: NSLayoutConstraint?
    var tim: CGFloat = 50.0
    var slidermultiplier: CGFloat = 0.6
    override func viewDidLoad() {
        super.viewDidLoad()
        widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
        
        
        [viewDrag,slizer].forEach{
            [=10=].translatesAutoresizingMaskIntoConstraints = false
            view.addSubview([=10=])
        }
        
        NSLayoutConstraint.activate([
            
            
            slizer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            slizer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            slizer.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.2),
            slizer.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
            
        ])
        
        
        slizer.addTarget(self, action: #selector(increase), for: .valueChanged)
        viewDrag.backgroundColor = .orange
        
        viewDrag.frame = CGRect(x: view.center.x-view.frame.width * 0.05, y: view.center.y-view.frame.height * 0.05, width: view.frame.width * 0.1, height: view.frame.height * 0.1)
        panGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.draggedView(_:)))
        viewDrag.isUserInteractionEnabled = true
        viewDrag.addGestureRecognizer(panGesture)
        
        
        
    
        
        
        oldCons = [
            viewDrag.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            
            viewDrag.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: tim),
            viewDrag.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
            widthConstraints!,
        ]
        NSLayoutConstraint.activate(oldCons)
        
        
    }
    
    
    @objc func sliderr() {
        
        
        
        NSLayoutConstraint.deactivate(oldCons)
        
        
        
        oldCons = [
            viewDrag.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            
            viewDrag.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -tim),
            viewDrag.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
            widthConstraints!,
        ]
        
        NSLayoutConstraint.activate(oldCons)
    }
    @objc func draggedView(_ sender: UIPanGestureRecognizer) {
        self.view.bringSubview(toFront: viewDrag)
        let translation = sender.translation(in: self.view)
        viewDrag.center = CGPoint(x: viewDrag.center.x + translation.x , y: viewDrag.center.y + translation.y)
        sender.setTranslation(CGPoint.zero, in: self.view)
        
        
        
        
        
    }
    
    
    
    @objc func increase() {
        slidermultiplier = CGFloat(slizer.value)
        widthConstraints?.isActive = false
        widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
        widthConstraints?.isActive = true
    }
    
}

视图“返回”的原因是因为您给了 viewDrag 自动布局约束...但是在您的 draggedView 函数中,您明确设置了它的框架(使用 viewDrag.center = CGPoint(. ..)).

这不会改变它的约束,一旦你做了其他事情让它更新,UIKit 就会re-position/re-size它基于它的约束。

不是设置 viewDrag.center 属性,而是为 Leading 和 CenterY(定位)创建变量约束,并更新它们的 .constant 值以移动查看。

看看这个 - 里面有很多评论可以帮助你弄清楚:

class SlideViewController: UIViewController {
    
    var slizer = UISlider()
    var viewDrag = UIImageView()

    var panGesture = UIPanGestureRecognizer()
    
    // Width, Leading and CenterY constraints for viewDrag
    var widthConstraints: NSLayoutConstraint!
    var viewDragLeadingConstraint: NSLayoutConstraint!
    var viewDragCenterYConstraint: NSLayoutConstraint!
    
    var tim: CGFloat = 50.0
    var slidermultiplier: CGFloat = 0.6
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [viewDrag,slizer].forEach{
            [=10=].translatesAutoresizingMaskIntoConstraints = false
            view.addSubview([=10=])
        }
        
        NSLayoutConstraint.activate([
            slizer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            slizer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            slizer.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.2),
            slizer.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
        ])
        
        slizer.addTarget(self, action: #selector(increase), for: .valueChanged)

        viewDrag.backgroundColor = .orange

        // no point setting a frame, since
        //  viewDrag has .translatesAutoresizingMaskIntoConstraints = false
        //viewDrag.frame = CGRect(x: view.center.x-view.frame.width * 0.05, y: view.center.y-view.frame.height * 0.05, width: view.frame.width * 0.1, height: view.frame.height * 0.1)
        
        // start with viewDrag
        //  width = "slidermultiplier" percent of view width
        widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
        // Leading = "tim" pts from view leading
        viewDragLeadingConstraint = viewDrag.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: tim)
        //  centered vertically
        viewDragCenterYConstraint = viewDrag.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        
        NSLayoutConstraint.activate([
            
            // viewDrag height will never change, so we can set it here
            viewDrag.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
            
            // activate the 3 "modifiable" constraints
            widthConstraints,
            viewDragLeadingConstraint,
            viewDragCenterYConstraint,
            
        ])
        
        panGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedView(_:)))

        viewDrag.isUserInteractionEnabled = true
        viewDrag.addGestureRecognizer(panGesture)
        
        // start the slider at the same percentage we've used
        //  for viewDrag's initial width
        slizer.value = Float(slidermultiplier)
        
    }
    
    @objc func draggedView(_ sender: UIPanGestureRecognizer) {
        // old swift syntax
        //self.view.bringSubview(toFront: viewDrag)
        self.view.bringSubviewToFront(viewDrag)
        
        let translation = sender.translation(in: self.view)
        viewDragLeadingConstraint.constant += translation.x
        viewDragCenterYConstraint.constant += translation.y
        
        // don't do this
        //viewDrag.center = CGPoint(x: viewDrag.center.x + translation.x , y: viewDrag.center.y + translation.y)
        
        sender.setTranslation(CGPoint.zero, in: self.view)
    }
    
    @objc func increase() {
        // get the new value of the slider
        slidermultiplier = CGFloat(slizer.value)
        
        // deactivate widthConstraints
        widthConstraints.isActive = false
        // create new widthConstraints with slider value as a multiplier
        widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
        // activate the new widthConstraints
        widthConstraints.isActive = true
    }
    
}