Android中实现一个可拖动的悬浮按钮,点击d出菜单的功能

Android中实现一个可拖动的悬浮按钮,点击d出菜单的功能,第1张

概述如图:        实现思路通过重写控件的onTouchEvent方法监听触摸效果通过View的setX()和setY()方法实现移动使用属性动画实现边缘吸附效果手指按下首先是处理手指按压下的事件,这里我们把拖拽标识符设置为false并记录当前点击的屏幕坐标。然后我们在移动事件处手指移

如图:

 

        

 

 

实现思路
通过重写控件的ontouchEvent方法监听触摸效果
通过VIEw的setX()和setY()方法实现移动
使用属性动画实现边缘吸附效果
手指按下
首先是处理手指按压下的事件,这里我们把拖拽标识符设置为false并记录当前点击的屏幕坐标。然后我们在移动事件处

手指移动
这里我们把拖拽标识符设置为true,因为手指移动了。然后我们需要计算手指移动了多少偏移量

//计算手指移动了多少int dx=rawX-lastX;int dy=rawY-lastY;

而后的两行代码表示控件需要移动的具体距离,后面有一个简单的边缘检测计算。最终通过调用setX以及setY方法实现控件的移动

手指松开
这里如果是拖拽动作我们才需要处理自己的逻辑否则直接跳过即可。在这里我们首先恢复了按钮的按压效果,在源代码中找到setpressed(boolean)方法,这是处理按钮点击效果用的,在这里当手指松开后我们需要恢复按钮原来的效果。然后在判断控件需要往哪边吸附,吸附的过程就是做属性动画而已,原理还是不断的改变setX方法让按钮靠边移动

代码区
关于自定义的拖拽VIEw (核心部分)
继承类(均可实现拖拽)

有的继承AppCompatimageVIEw下的ImageVIEw
有的继承floatingActionbutton(如果继承此类需要导入以下依赖)

compile 'com.androID.support:design:26.1.0'implementation 'com.androID.support:appcompat-v7:26.1.0'

DragfloatActionbutton (Kotlin版)

package com.example.mychartdemoimport androID.animation.ObjectAnimatorimport androID.annotation.Suppresslintimport androID.content.Contextimport androID.util.AttributeSetimport androID.util.Logimport androID.vIEw.MotionEventimport androID.vIEw.VIEwGroupimport androID.vIEw.animation.DecelerateInterpolatorimport androID.Widget.ImageVIEw//https://blog.csdn.net/qq_20451879/article/details/87876673//效果可以@Suppresslint("AppCompatCustomVIEw")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    public var isDrag: Boolean = false    public var isRight: Boolean = false    public var istop: Boolean = true    public var isCanMove: Boolean = true    overrIDe fun ontouchEvent(event: MotionEvent): Boolean {        val rawX = event.rawX.toInt()        val rawY = event.rawY.toInt()        Log.i("打印X轴、Y轴坐标:","rawX:$rawX  ,rawY: $rawY")         if (!isCanMove){//不可移动             return super.ontouchEvent(event)         }        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 -> {                isDrag = !(parentHeight <= 0 || parentWIDth === 0)                /*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()                    isRight = true                } else {                    //靠左吸附                    val oa = ObjectAnimator.offloat(this, "x", x, 0F)                    oa.interpolator = DecelerateInterpolator()                    oa.duration = 500                    oa.start()                    isRight = false                }                //判断是否位于上半部分                istop = rawY <= parentHeight/2                Log.i("打印是否位于顶部:",""+istop)            }        }        //如果是拖拽则消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"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    xmlns:tools="http://schemas.androID.com/tools"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    androID:orIEntation="vertical"    tools:context=".MainActivity3">    <com.example.mychartdemo.DragfloatActionbutton        androID:layout_wIDth="45dp"        androID:layout_height="45dp"        androID:ID="@+ID/img_btn"        androID:src="@mipmap/ic_launcher"></com.example.mychartdemo.DragfloatActionbutton></linearLayout>

 MainActivity

package com.example.mychartdemoimport androID.graphics.drawable.BitmapDrawableimport androID.os.Bundleimport androID.util.Logimport androID.vIEw.VIEwimport androID.Widget.ImageVIEwimport androID.Widget.PopupWindowimport androID.Widget.RadioGroupimport androIDx.appcompat.app.AppCompatActivityimport com.example.mychartdemo.databinding.ActivityMain3Bindingclass MainActivity : AppCompatActivity(),VIEw.OnClickListener{    private  var popupWindow: PopupWindow? = null    private lateinit var binding: ActivityMain3Binding    overrIDe fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        binding = ActivityMain3Binding.inflate(layoutInflater)        setContentVIEw(binding.root)        binding.imgBtn.setonClickListener {                     if (popupWindow == null) {                initPopWindow()                //设置不可拖动                binding.imgBtn.isCanMove = false            } else if (popupWindow != null && popupWindow?.isShowing == true) {                popupWindow?.dismiss()                popupWindow = null                //设置可拖动                binding.imgBtn.isCanMove = true                            }        }    }    private fun initPopWindow() {        var vIEw: VIEw? = null        if(binding.imgBtn.isRight){           vIEw = VIEw.inflate(this, R.layout.popwindow_vIEw, null)        }else{            vIEw = VIEw.inflate(this, R.layout.popwindow_left_vIEw, null)        }        val popimg_1: ImageVIEw = vIEw.findVIEwByID<ImageVIEw>(R.ID.popimg_1)        popimg_1.setonClickListener(this)        val popimg_2: ImageVIEw = vIEw.findVIEwByID<ImageVIEw>(R.ID.popimg_2)        popimg_2.setonClickListener(this)        val popimg_3: ImageVIEw = vIEw.findVIEwByID<ImageVIEw>(R.ID.popimg_3)        popimg_3.setonClickListener(this)        popupWindow = PopupWindow(            vIEw,            DensityUtil.dip2px(this, 160F),            RadioGroup.LayoutParams.WRAP_CONTENT        )        popupWindow?.settouchable(true) //设置可以点击        popupWindow?.setoutsIDetouchable(false) //点击外部关闭        // popupWindow.setBackgroundDrawable(new colorDrawable());//设置背景        // popupWindow.setBackgroundDrawable(new colorDrawable());//设置背景        popupWindow?.setBackgroundDrawable(BitmapDrawable())        if (binding.imgBtn.istop){            Log.i("打印是否位于顶部111:",""+binding.imgBtn.istop)            popupWindow?.showAsDropDown(binding.imgBtn)        }else{            if(binding.imgBtn.isRight){                Log.i("打印是否位于顶部222:",""+binding.imgBtn.istop)                popupWindow?.showAsDropDown(binding.imgBtn)            }else{                Log.i("打印是否位于顶部3333:",""+binding.imgBtn.istop)                popupWindow?.showAsDropDown(binding.imgBtn,0,DensityUtil.dip2px(this,-200F))            }        }    }    overrIDe fun onClick(v: VIEw) {        when (v.ID) {            R.ID.popimg_1 -> {                if (popupWindow != null) {                    popupWindow?.dismiss()                    popupWindow = null                    //设置可拖动                    binding.imgBtn.isCanMove = true                  Log.i("点击了","111")                }else{                    Log.i("点击了","2222")                }            }            R.ID.popimg_2 -> {                if (popupWindow != null) {                    popupWindow?.dismiss()                    popupWindow = null                    //设置可拖动                    binding.imgBtn.isCanMove = true                }            }            R.ID.popimg_3 -> {                if (popupWindow != null) {                    popupWindow?.dismiss()                    popupWindow = null                    //设置可拖动                    binding.imgBtn.isCanMove = true                }            }        }    }}

popwindow_vIEw 布局文件

  

<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    androID:orIEntation="vertical">    <linearLayout        androID:layout_wIDth="match_parent"        androID:layout_height="50dp"        androID:orIEntation="horizontal">        <TextVIEw            androID:layout_wIDth="0dp"            androID:layout_weight="1"            androID:layout_height="match_parent"            androID:text="满刻度"            androID:gravity="center|right"            androID:paddingRight="10dp"></TextVIEw>        <ImageVIEw            androID:layout_wIDth="50dp"            androID:layout_height="50dp"            androID:src="@mipmap/ic_launcher"            androID:ID="@+ID/popimg_1"></ImageVIEw>    </linearLayout>    <linearLayout        androID:layout_wIDth="match_parent"        androID:layout_height="50dp"        androID:orIEntation="horizontal">        <TextVIEw            androID:layout_wIDth="0dp"            androID:layout_weight="1"            androID:layout_height="match_parent"            androID:text="数据明细"            androID:gravity="center|right"            androID:paddingRight="10dp"></TextVIEw>        <ImageVIEw            androID:layout_wIDth="50dp"            androID:layout_height="50dp"            androID:src="@mipmap/ic_launcher"            androID:ID="@+ID/popimg_2"></ImageVIEw>    </linearLayout>    <linearLayout        androID:layout_wIDth="match_parent"        androID:layout_height="50dp"        androID:orIEntation="horizontal">        <TextVIEw            androID:layout_wIDth="0dp"            androID:layout_weight="1"            androID:layout_height="match_parent"            androID:text="选择日期"            androID:gravity="center|right"            androID:paddingRight="10dp"></TextVIEw>        <ImageVIEw            androID:layout_wIDth="50dp"            androID:layout_height="50dp"            androID:src="@mipmap/ic_launcher"            androID:ID="@+ID/popimg_3"></ImageVIEw>    </linearLayout></linearLayout>

  popwindow_left_vIEw  左边布局文件

<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    androID:orIEntation="vertical">    <linearLayout        androID:layout_wIDth="match_parent"        androID:layout_height="50dp"        androID:orIEntation="horizontal">        <ImageVIEw            androID:layout_wIDth="50dp"            androID:layout_height="50dp"            androID:src="@mipmap/ic_launcher"            androID:ID="@+ID/popimg_1"></ImageVIEw>        <TextVIEw            androID:layout_wIDth="0dp"            androID:layout_weight="1"            androID:layout_height="match_parent"            androID:text="满刻度"            androID:gravity="center|left"            androID:paddingleft="10dp"></TextVIEw>    </linearLayout>    <linearLayout        androID:layout_wIDth="match_parent"        androID:layout_height="50dp"        androID:orIEntation="horizontal">        <ImageVIEw            androID:layout_wIDth="50dp"            androID:layout_height="50dp"            androID:src="@mipmap/ic_launcher"            androID:ID="@+ID/popimg_2"></ImageVIEw>        <TextVIEw            androID:layout_wIDth="0dp"            androID:layout_weight="1"            androID:layout_height="match_parent"            androID:text="数据明细"            androID:gravity="center|left"            androID:paddingleft="10dp"></TextVIEw>    </linearLayout>    <linearLayout        androID:layout_wIDth="match_parent"        androID:layout_height="50dp"        androID:orIEntation="horizontal">        <ImageVIEw            androID:layout_wIDth="50dp"            androID:layout_height="50dp"            androID:src="@mipmap/ic_launcher"            androID:ID="@+ID/popimg_3"></ImageVIEw>        <TextVIEw            androID:layout_wIDth="0dp"            androID:layout_weight="1"            androID:layout_height="match_parent"            androID:text="选择日期"            androID:gravity="center|left"            androID:paddingleft="10dp"></TextVIEw>    </linearLayout></linearLayout>

  完成

 

 

 

参考于:https://blog.csdn.net/qq_20451879/article/details/87876673

 

 

总结

以上是内存溢出为你收集整理的Android中实现一个可拖动的悬浮按钮,点击d出菜单的功能全部内容,希望文章能够帮你解决Android中实现一个可拖动的悬浮按钮,点击d出菜单的功能所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1086650.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存