与平移手势闪烁视图相关的问题

Posted

技术标签:

【中文标题】与平移手势闪烁视图相关的问题【英文标题】:Problem related to pan gesture flickers view 【发布时间】:2020-05-14 15:00:37 【问题描述】:

我正在尝试使用平移手势向上/向下移动底部视图。它有效,但存在闪烁问题,因此过渡不顺畅。

这里是代码

@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 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
           
        
    
 

在图片中,您可以检查实际问题

【问题讨论】:

你能分享演示示例项目来测试这个吗? 【参考方案1】:

问题是您反复获取触摸位置在底部视图中 ...然后更改底部视图大小。

由于触摸 Y 是相对于视图的高度,所以它会四处弹跳。

试试这个...

添加类属性:

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()
        
    

每次“结束”拖动/调整大小过程时,您都需要将 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
    

【讨论】:

附带说明,您不需要此行self.bottomView.layoutIfNeeded() 还有一件事,如果手势从上到下移动到其高度的 20% 并且反之亦然,则可以使用此代码设置最小高度? @EICaptainv2.0 - 不确定您所说的“如果手势从上到下移动到其高度的 20%,反之亦然” 是什么意思?另一个旁注:我用更好的panAction() 实现编辑了我的答案,它处理维护状态(所以高度不会在拖动/释放/拖动/释放等时跳跃)。 如果视图将位置从 0 拖动到 40 则视图应该完全向上移动,反之亦然从上到下

以上是关于与平移手势闪烁视图相关的问题的主要内容,如果未能解决你的问题,请参考以下文章

平移手势后将视图返回到原始位置,快速

UIScrollview 子视图在缩放后无法识别平移手势

在颤振中如何使带有平移手势的内部小部件不会与PageView冲突

在 iOS Swift 中使用键盘平移手势处理文本输入视图移动

UIView/Drawer 使用平移/滑动手势

使用平移手势选择多个表格视图单元格