I am trying to move the bottom view up/ down using a pan gesture. It worked but has an issue of flickering and therefore it's not a smooth transition.
Here is the code
@IBOutlet weak var bottomViewHeight: NSLayoutConstraint!
@IBOutlet weak var bottomView: UIView!
var maxHeight: CGFloat = 297
var minHeight: CGFloat = 128
let panGest = PanVerticalScrolling(target: self, action: #selector(panAction(sender:)))
bottomView.addGestureRecognizer(panGest)
@objc func panAction(sender: UIPanGestureRecognizer) {
if sender.state == .changed {
let endPosition = sender.location(in: self.bottomView)
let differenceHeight = maxHeight - endPosition.y
if differenceHeight < maxHeight && differenceHeight > minHeight {
bottomViewHeight.constant = differenceHeight
self.bottomView.layoutIfNeeded()
}
}
}
Here is the gesture class
class PanVerticalScrolling : UIPanGestureRecognizer {
override init(target: Any?, action: Selector?) {
super.init(target: target, action: action)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
if state == .began {
let vel = velocity(in: self.view)
if abs(vel.x) > abs(vel.y) {
state = .cancelled
}
}
}
}
And here in the image, you can check the actual issue
The problem is that you are repeatedly getting the touch position in the bottom view ... and then changing bottom view size.
Since the touch Y is relative to the height of the view, it's bouncing around.
Try this...
Add a class property:
var initialY: CGFloat = -1.0
and change your panAction()
to this:
@objc func panAction(sender: UIPanGestureRecognizer) {
if sender.state == .changed {
if initialY == -1.0 {
initialY = sender.location(in: self.view).y
}
let endPositionY = sender.location(in: self.view).y - initialY
let differenceHeight = maxHeight - endPositionY
if differenceHeight < maxHeight && differenceHeight > minHeight {
bottomViewHeight.constant = differenceHeight
self.bottomView.layoutIfNeeded()
}
}
}
You'll need to reset initialY
to -1
each time you "end" the drag / resize process.
Edit
A better way - maintains current state:
// these will be used inside panAction()
var initialY: CGFloat = -1.0
var initialHeight: CGFloat = -1.0
@objc func panAction(sender: UIPanGestureRecognizer) {
if sender.state == .changed {
let endPositionY = sender.location(in: self.view).y - initialY
let differenceHeight = self.initialHeight - endPositionY
if differenceHeight < maxHeight && differenceHeight > minHeight {
bottomViewHeight.constant = differenceHeight
}
}
if sender.state == .began {
// reset position and height tracking properties
self.initialY = sender.location(in: self.view).y
self.initialHeight = bottomViewHeight.constant
}
}