与平移手势闪烁视图相关的问题
Problem related to pan gesture flickers view
我正在尝试使用平移手势向上/向下移动底部视图。它有效,但存在闪烁问题,因此它不是一个平滑的过渡。
这是代码
@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()
}
}
}
这是手势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
}
}
}
}
在图像中,您可以检查实际问题
问题是您在底部视图中重复获取触摸位置 ...然后更改底部视图大小。
由于触摸 Y 是相对于视图的高度,它会四处弹跳。
试试这个...
添加一个class 属性:
var initialY: CGFloat = -1.0
并将您的 panAction()
更改为:
@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()
}
}
}
每次 "end" 拖动/调整大小过程时,您都需要将 initialY
重置为 -1
。
编辑
更好的方法 - 保持当前状态:
// 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
}
}
我正在尝试使用平移手势向上/向下移动底部视图。它有效,但存在闪烁问题,因此它不是一个平滑的过渡。
这是代码
@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()
}
}
}
这是手势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
}
}
}
}
在图像中,您可以检查实际问题
问题是您在底部视图中重复获取触摸位置 ...然后更改底部视图大小。
由于触摸 Y 是相对于视图的高度,它会四处弹跳。
试试这个...
添加一个class 属性:
var initialY: CGFloat = -1.0
并将您的 panAction()
更改为:
@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()
}
}
}
每次 "end" 拖动/调整大小过程时,您都需要将 initialY
重置为 -1
。
编辑
更好的方法 - 保持当前状态:
// 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
}
}