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

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android开发中,Kotlin是一种常用的现代化语言,它与Java一起被用于构建Android应用。悬浮按钮(FloatingActionButton,简称FAB)是一种设计模式,通常用于表示某个操作或功能,它通常位于屏幕底部或角落,且会随着内容滚动而保持可见。 在Kotlin中使用FloatingActionButton,你可以遵循以下步骤: 1. 添加依赖:如果你使用的是Kotlin coroutines(协程),确保在build.gradle文件中添加了`androidx.coordinatorlayout.widget.CoordinatorLayout`和`androidx.appcompat.widget.AppCompatImageView`等库。 ```groovy dependencies { implementation 'com.google.android.material:material:1.4.0' // or the latest version } ``` 2. 在布局文件中(XML)添加FAB: ```xml <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_add" app:layout_anchor="@id/coordinator_layout" app:layout_anchorGravity="bottom|end" /> ``` - `android:id`是你给按钮的ID。 - `android:src`设置图标资源。 - `app:layout_anchor`指定它应该锚定到哪个View(比如CoordinatorLayout)。 - `app:layout_anchorGravity`定义了按钮在Anchor View中的位置,这里通常是底部和右侧。 3. 在Kotlin中处理点击事件: ```kotlin val fab = findViewById<FloatingActionButton>(R.id.fab) fab.setOnClickListener { // 在这里添加你的点击事件处理逻辑 } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值