我在屏幕中间有一个黑色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
}
答案 0 :(得分:8)
当您使用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
}
}