android可拖拽悬浮控件和Kotlin的可拖拽悬浮控件/可拖拽悬浮按钮带Demo附件

Posted 骑鲸鱼的企鹅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android可拖拽悬浮控件和Kotlin的可拖拽悬浮控件/可拖拽悬浮按钮带Demo附件相关的知识,希望对你有一定的参考价值。

本文讲解的是一个实现了可拖拽的悬浮按钮,并添加了吸附边框的功能。

借鉴于:https://www.jianshu.com/p/4f55bcbc1b83

在此之前,先了解下其简单的使用方式吧:

原文地址:https://blog.csdn.net/w630886916/article/details/82113050

Demo地址:https://download.csdn.net/download/w630886916/10629168

* 可拖拽的悬浮控件按钮
* 直接xml布局里引用即可。
* 要设置setOnClickListener点击事件,即可实现拖拽和点击功能。
* 尺寸大小,样式及背景图片遵循ImageView即可。

如图:

 

代码:

主页面:

class MainActivity : AppCompatActivity() 

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        actionButton.setOnClickListener 
            Toast.makeText(this,"触发了可拖拽按钮的点击事件",Toast.LENGTH_SHORT).show()
        
    

核心控件(kotlin):

(java代码附件里有,使用方法一样)

/**
 * 可拖拽的悬浮控件按钮
 * 2018-08-27
 * 直接xml布局里引用即可。
 * 要设置setOnClickListener点击事件,即可实现拖拽和点击功能。
 * 尺寸大小,样式及背景图片遵循ImageView即可。
 */
class DragFloatActionButton : ImageView 
    private var parentHeight: Int = 0
    private var parentWidth: Int = 0

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    private var lastX: Int = 0
    private var lastY: Int = 0

    private var isDrag: Boolean = false

    override fun onTouchEvent(event: MotionEvent): Boolean 
        val rawX = event.rawX.toInt()
        val rawY = event.rawY.toInt()
        when (event.action and MotionEvent.ACTION_MASK) 
            MotionEvent.ACTION_DOWN -> 
                isPressed = true
                isDrag = false
                parent.requestDisallowInterceptTouchEvent(true)
                lastX = rawX
                lastY = rawY
                val parent: ViewGroup
                if (getParent() != null) 
                    parent = getParent() as ViewGroup
                    parentHeight = parent.height
                    parentWidth = parent.width
                
            
            MotionEvent.ACTION_MOVE -> 
                if (parentHeight <= 0 || parentWidth === 0) 
                    isDrag = false
                 else 
                    isDrag = true
                
                val dx = rawX - lastX
                val dy = rawY - lastY
                //这里修复一些华为手机无法触发点击事件
                val distance = Math.sqrt((dx * dx + dy * dy).toDouble()).toInt()
                if (distance == 0) 
                    isDrag = false
                 else 
                    var x = x + dx
                    var y = y + dy
                    //检测是否到达边缘 左上右下
                    x = if (x < 0) 0F else if (x > parentWidth - width) (parentWidth - width).toFloat() else x
                    y = if (getY() < 0) 0F else if (getY() + height > parentHeight) (parentHeight - height).toFloat() else y
                    setX(x)
                    setY(y)
                    lastX = rawX
                    lastY = rawY
                    Log.i("aa", "isDrag=" + isDrag + "getX=" + getX() + ";getY=" + getY() + ";parentWidth=" + parentWidth)
                
            
            MotionEvent.ACTION_UP -> if (!isNotDrag()) 
                //恢复按压效果
                isPressed = false
                //Log.i("getX="+getX()+";screenWidthHalf="+screenWidthHalf);
                if (rawX >= parentWidth / 2) 
                    //靠右吸附
                    animate().setInterpolator(DecelerateInterpolator())
                            .setDuration(500)
                            .xBy(parentWidth - width - x)
                            .start()
                 else 
                    //靠左吸附
                    val oa = ObjectAnimator.ofFloat(this, "x", x, 0F)
                    oa.setInterpolator(DecelerateInterpolator())
                    oa.setDuration(500)
                    oa.start()
                
            
        
        //如果是拖拽则消s耗事件,否则正常传递即可。
        return !isNotDrag() || super.onTouchEvent(event)
    

    private fun isNotDrag(): Boolean 
        return !isDrag && (x == 0f || x == (parentWidth - width).toFloat())
    

布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.internal.test.floatingactionbuttontest.DragFloatActionButton
        android:id="@+id/actionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/ic_launcher"/>

</android.support.constraint.ConstraintLayout>

 

如果你想看控件原介绍,文初有链接。

基本上功能简单,直接使用即可。

附件:

Demo地址:https://download.csdn.net/download/w630886916/10629168

 

 

以上是关于android可拖拽悬浮控件和Kotlin的可拖拽悬浮控件/可拖拽悬浮按钮带Demo附件的主要内容,如果未能解决你的问题,请参考以下文章

Android activity内实现可拖拽悬浮控件

Android activity内实现可拖拽悬浮控件

Android自定义View之可拖拽悬浮控件 代码赏析

Android——基于ConstraintLayout实现的可拖拽位置控件

HTML5+Three.js实现的可拖拽镜面反射与球面折射全景动画

Android高级控件——自定义ListView高仿一个QQ可拖拽列表的实现