栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

动画与过渡(六)、使用ViewDragHelper实现平滑拖动动画

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

动画与过渡(六)、使用ViewDragHelper实现平滑拖动动画

Android动画与概述主要涵盖了以下内容:

  • 动画与过渡(一)、视图动画概述与使用
  • 动画与过渡(二)、视图动画进阶:对Animation进行定义扩展
  • 动画与过渡(三)、插值器和估值器概述与使用
  • 动画与过渡(四)、使用Layout、offset、layoutParam实现位移动画
  • 动画与过渡(五)、使用scrollTo、scrollBy、Scroller实现滚动动画
  • 动画与过渡(六)、使用ViewDragHelper实现平滑拖动动画
  • 动画与过渡(七)、为ViewGroup添加入场动画,LayoutAnimation使用概述
  • 动画与过渡(八)、为Viewgroup提供删除、新增平滑动画效果,LayoutTransition使用概述
  • 动画与过渡(九)、Svg动画使用概述,Vector Drawable使用,三方SVGA框架使用
  • 动画与过渡(十)、Property Animation动画使用概述
  • 动画与过渡(十一)、使用Fling动画移动视图,FlingAnimation动画使用概述
  • 动画与过渡(十二)、使用物理弹簧动画为视图添加动画,SpringAnimation动画使用概述
  • 动画与过渡(十三)、视图、Activity过渡转场动画使用概述
  • 动画与过渡(十四)、Lottie动画使用概述
  • 动画与过渡实战(十五)、仿今日头条栏目拖动排序效果
  • 动画与过渡实战(十六)、仿IOS侧滑删除效果
  • 动画与过渡实战(十七)、仿探探卡片翻牌效果

在之前的文章中,分别介绍了使用layout(left, top, right, bottom)、layoutParams、offsetLeftAndRight/offsetTopAndBottom、scrollBy/scrollTo、Scroller方式实现移动效果,本篇文章,将讲解一个更高阶的实现移动效果的方式—ViewDragHelper。

1、ViewDragHelper使用方法介绍

ViewDragHelper使用十分简单,基本上就是固定的使用套路。因为ViewDragHelper是一个拖动、移动的辅助类,一般情况下,我们会使用在自定义view or viewgroup之中。

  • 使用ViewDragHelper.create(this, object : ViewDragHelper.Callback() {}方法创建一个ViewDragHelper对象
val itemDragHelper = ViewDragHelper.create(this, object : ViewDragHelper.Callback() {
...//do somethings
}
  • 在View or ViewGroup中的事件拦截使用viewDragHelper的方法进行*事件接管*。
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
     return mItemViewDragHelper?.shouldInterceptTouchEvent(ev) == true
 }

 override fun onTouchEvent(event: MotionEvent): Boolean {
     if (event.action == MotionEvent.ACTION_DOWN) {
         this.performClick()
     }
     mItemViewDragHelper?.processTouchEvent(event)
     return true
 }
  • 重写computeScroll方法,在其中处理刷新
override fun computeScroll() {
    if (mItemViewDragHelper?.continueSettling(true) == true) {
        ViewCompat.postInvalidateOnAnimation(this)
    }
}
  • 实现ViewDragHelper.Callback的方法,进行逻辑处理操作。

下面介绍下ViewDragHelper.Callback常用的方法

//用来判断需要拦截那个view对象用来拖动
override fun tryCaptureView(child: View, pointerId: Int): Boolean 

//用来控制拖动的边界,默认情况下,left和top就是系统默认计算的边界值
override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int 
override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int 

//手指释放时候的反馈
override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) 

//触摸边界时候回调
override fun onEdgeDragStarted(edgeFlags: Int, pointerId: Int)
2、实现一个简单的拖动移动效果


上面三个分别是普通拖动(无回弹效果)、推动松手后回弹、在布局边缘拖动效果。



   

   

   


class SimpleViewDragHelperUseView2 @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayoutCompat(context, attrs, defStyleAttr) {

    private var mTouch1: TextView? = null
    private var mTouch2: TextView? = null
    private var mTouch3: TextView? = null
    private var mItemViewDragHelper: ViewDragHelper? = null

    private var mTouch1OriginLeft: Int = 0
    private var mTouch1OriginTop: Int = 0
    private var mTouch2OriginLeft: Int = 0
    private var mTouch2OriginTop: Int = 0
    private var mTouch3OriginLeft: Int = 0
    private var mTouch3OriginTop: Int = 0

    init {

        isFocusableInTouchMode = true

        isMotionEventSplittingEnabled = true

        mItemViewDragHelper =
            ViewDragHelper.create(this, object : ViewDragHelper.Callback() {

                override fun getViewHorizontalDragRange(child: View): Int {
                    return mItemViewDragHelper?.touchSlop ?: 0
                }

                override fun getViewVerticalDragRange(child: View): Int {
                    return mItemViewDragHelper?.touchSlop ?: 0
                }

                
                override fun tryCaptureView(child: View, pointerId: Int): Boolean {
                    return child == mTouch1 || child == mTouch2
                }

                
                override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
                    return left
                }

                
                override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
                    return top
                }

                
                override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
                    releasedChild.let {
                       if (it == mTouch2) {
                            mItemViewDragHelper?.smoothSlideViewTo(
                                it,
                                mTouch2OriginLeft,
                                mTouch2OriginTop
                            )
                        } else if (it == mTouch3) {
                            mItemViewDragHelper?.smoothSlideViewTo(
                                it,
                                mTouch3OriginLeft,
                                mTouch3OriginTop
                            )
                        }
                        ViewCompat.postInvalidateOnAnimation(this@SimpleViewDragHelperUseView2)
                    }
                }

                
                override fun onEdgeDragStarted(edgeFlags: Int, pointerId: Int) {
                   //边界拖动触发后,设置拖动事件捕获touch3
                    mTouch3?.let {
                        mItemViewDragHelper?.captureChildView(it, pointerId)
                    }
                }

            })
            //设置边界拖动可用
        mItemViewDragHelper?.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT)
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        mTouch1 = findViewById(R.id.tvTouchV1)
        mTouch2 = findViewById(R.id.tvTouchV2)
        mTouch3 = findViewById(R.id.tvTouchV3)
    }

    override fun computeScroll() {
        if (mItemViewDragHelper?.continueSettling(true) == true) {
            ViewCompat.postInvalidateOnAnimation(this)
        }
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)
        mTouch1OriginLeft = mTouch1?.left ?: 0
        mTouch1OriginTop = mTouch1?.top ?: 0
        mTouch2OriginLeft = mTouch2?.left ?: 0
        mTouch2OriginTop = mTouch2?.top ?: 0
        mTouch3OriginLeft = mTouch3?.left ?: 0
        mTouch3OriginTop = mTouch3?.top ?: 0
    }

    private var startX = 0F
    private var startY = 0F

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        var result: Boolean = mItemViewDragHelper?.shouldInterceptTouchEvent(ev) == true
        val curX = ev.x
        val curY = ev.y
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                startX = curX
                startY = curY
            }
            MotionEvent.ACTION_MOVE -> {
                if (abs(curX - startX) > mItemViewDragHelper?.touchSlop ?: 0 || abs(curY - startY) > mItemViewDragHelper?.touchSlop ?: 0) {
                    result = true
                }
            }
        }
        return result
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            this.performClick()
        }
        mItemViewDragHelper?.processTouchEvent(event)
        return true
    }

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/445422.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号