使用UIPanGestureRecognizer更新约束

ker*_*lda 2 uigesturerecognizer ios uipangesturerecognizer swift

我在屏幕中间有一个黑色separatorView,分隔topContainerView(橙色)和bottomContainerView(绿色).可以使用panGesture上下拖动separatorView,但我无法获得顶视图和底视图来更新其约束并调整大小.橙色视图的底部和绿色视图的顶部应始终与separatorView一起使用.

这是我的代码(UPDATED包含变量声明):

let separatorView: UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.black
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

let topContainerView : UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.orange
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

let bottomContainerView : UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.green
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

override func viewDidLoad() {
        super.viewDidLoad()
        self.addViews()
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(detectPan(recognizer:)))
        panGesture.delaysTouchesBegan = false
        panGesture.delaysTouchesEnded = false
        separatorView.addGestureRecognizer(panGesture)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func addViews() {
        
        view.addSubview(topContainerView)
        view.addSubview(bottomContainerView)
        view.addSubview(separatorView)
        
        separatorView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        separatorView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        separatorView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        separatorView.heightAnchor.constraint(equalToConstant: 50).isActive = true
        
        topContainerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        topContainerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        topContainerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        topContainerView.bottomAnchor.constraint(equalTo: separatorView.topAnchor).isActive = true
        
        bottomContainerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        bottomContainerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        bottomContainerView.topAnchor.constraint(equalTo: separatorView.bottomAnchor).isActive = true
        bottomContainerView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }
    
    func detectPan(recognizer: UIPanGestureRecognizer) {
        let translation = recognizer.translation(in: self.view)
        separatorView.center = CGPoint(x: view.center.x, y: lastLocation.y + translation.y)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.bringSubview(toFront: separatorView)
        lastLocation = separatorView.center
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在此输入图像描述

Pau*_*w11 12

当您使用Autolayout时,您不能简单地修改元素的框架(这是您通过更改center属性隐式执行的操作).好吧,你可以,但它不会影响任何其他元素(如你所发现的),一旦触发Autolayout,你的框架更改将被重置.

您需要操纵约束,以便Autolayout生成您想要的结果.

在这种情况下,您需要修改constant约束的属性,该约束将分隔符绑定到视图的中心.您可以使用平移手势识别器的转换值来执行此操作.唯一棘手的一点是这个平移在平移开始时相对于0,所以你需要包含任何前一个平移的任何偏移.

let separatorView: UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.black
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

let topContainerView : UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.orange
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

let bottomContainerView : UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.green
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

var centerConstraint: NSLayoutConstraint!

var startingConstant: CGFloat  = 0.0

override func viewDidLoad() {
    super.viewDidLoad()
    self.addViews()
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(detectPan(recognizer:)))
    panGesture.delaysTouchesBegan = false
    panGesture.delaysTouchesEnded = false
    separatorView.addGestureRecognizer(panGesture)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func addViews() {

    view.addSubview(topContainerView)
    view.addSubview(bottomContainerView)
    view.addSubview(separatorView)

    separatorView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    separatorView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true

    self.centerConstraint = separatorView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    self.centerConstraint.isActive = true

    separatorView.heightAnchor.constraint(equalToConstant: 50).isActive = true

    topContainerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    topContainerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    topContainerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    topContainerView.bottomAnchor.constraint(equalTo: separatorView.topAnchor).isActive = true

    bottomContainerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    bottomContainerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    bottomContainerView.topAnchor.constraint(equalTo: separatorView.bottomAnchor).isActive = true
    bottomContainerView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}

func detectPan(recognizer: UIPanGestureRecognizer) {

    switch recognizer.state {
    case .began:
        self.startingConstant = self.centerConstraint.constant
    case .changed:
        let translation = recognizer.translation(in: self.view)
        self.centerConstraint.constant = self.startingConstant + translation.y
    default:
        break
    }
}
Run Code Online (Sandbox Code Playgroud)