Android 加入可拖动布局的方法

418 阅读1分钟

运用 ViewDragHelper

首先要实现容器 View, 子 View 在此容器中可拖动

package com.lujianfei.dragdemo

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.customview.widget.ViewDragHelper

/**
 * 可拖拽的 View
 */
class FloatingDraggerView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {

    private val TAG = this.javaClass.simpleName

    private var viewDragHelper: ViewDragHelper? = null
    private var mFirstChildView: View? = null

    init {
        viewDragHelper = ViewDragHelper.create(this, 1.0f, object : ViewDragHelper.Callback() {
            override fun tryCaptureView(child: View, pointerId: Int): Boolean {
                return true
            }

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

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

            /**
             * 加入松手后靠边处理
             */
            override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
                var x = mFirstChildView?.x?:0f
                val y = mFirstChildView?.y?:0f
                x = if (x < measuredWidth / 2) {
                    0f
                } else {
                    (measuredWidth - releasedChild.measuredWidth).toFloat()
                }
                // 移动到指定位置
                viewDragHelper?.smoothSlideViewTo(releasedChild, x.toInt(), y.toInt())
                invalidate()
            }
        })
    }


    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        if (childCount > 0) {
            mFirstChildView = getChildAt(0)
        }
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        return viewDragHelper?.shouldInterceptTouchEvent(ev)?:false
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        viewDragHelper?.processTouchEvent(event)
        return true
    }

    override fun computeScroll() {
        if (viewDragHelper?.continueSettling(true) == true) {
            invalidate()
        }
    }
}

使用方法

在布局中使用上面定义的布局容器,里面的子 View 即可拖动

<?xml version="1.0" encoding="utf-8"?>
<com.lujianfei.dragdemo.FloatingDraggerView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/bt_drag"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@mipmap/ic_launcher"
        />
</com.lujianfei.dragdemo.FloatingDraggerView>