Android Activity通用悬浮可拖拽View封装的思路详解

目录
  • 1,背景
  • 2,思路
    • 2.1,封装通用的基础悬浮View
    • 2.1,继承通用View
    • 2.3,设计view的控制器
    • 2.4,view的添加和使用

1,背景

在开发中总会遇到一个可拖拽的悬浮View,不管是在开发中,还是在线上,都时长有这样的控件,我们通常遇到这种情况,经常需要自己封装,需要耗费时间,我这边封装了一个可以通用的悬浮可拖拽View,这样使用的时候,只需要传入自己要设计的样式和位置既可

2,思路

2.1,封装通用的基础悬浮View

设计通用的父View

1,传入的childView是可以自定义layout,可以传入任何样式

childView = setChildView()

2,可以设置初始的位置

layoutParams = setChildInitLayoutParams()

3,可以修改自定义view控件

setChildAction(childView)

4,提供点击事件处理

protected abstract fun setEventClick()

子view继承父view就可以实现自己想要的功能了

abstract class AbsParentDragView : FrameLayout, View.OnTouchListener {

    //需要添加的子控件
    private var childView: View? = null
    //子控件的宽
    protected var childWidth: Int = 0
    //子控件的高
    protected var childHeight: Int = 0
    //子控件的位置属性
    lateinit var layoutParams: LayoutParams
    //点击区域偏移量
    private var regionW: Int = 0
    //判断是否可以移动
    private var isCanMove: Boolean = false

    private val MIN_TAP_TIME = 1000

    private val MIN_DISTANCE_MOVE = 4

    private var mState = TouchState.STATE_STOP

    private var distance: Int = 0

    private enum class TouchState {
        STATE_MOVE, STATE_STOP
    }

    constructor(context: Context) : super(context) {
        initView()
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        initView()
    }

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

    private fun initView() {

        childView = setChildView()

        setChildAction(childView)
        addView(childView)
        setOnTouchListener(this)
        layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)

        regionW = DensityUtil.dip2px(context, 3f)
        distance = DensityUtil.dip2px(context,1f) * MIN_DISTANCE_MOVE

        post {
            childView?.width?.let {
                childWidth = it
            }
            childView?.height?.let {
                childHeight = it
            }

            layoutParams = setChildInitLayoutParams()
            initLayoutParams()
        }

    }

    protected abstract fun setChildView(): View?

    protected abstract fun setChildInitLayoutParams(): FrameLayout.LayoutParams

    protected abstract fun setChildAction(childView: View?)

    private fun initLayoutParams() {
        layoutParams.gravity = Gravity.LEFT or Gravity.TOP
        childView?.layoutParams = layoutParams
    }

    private fun updateLayoutParams(dx: Int, dy: Int) {
        layoutParams.gravity = Gravity.LEFT or Gravity.TOP
        layoutParams.leftMargin = dx - childWidth / 2
        layoutParams.topMargin = dy - childHeight / 2 - StateUtils.getStatusBarHeight(context)
        childView?.layoutParams = layoutParams
    }

    private var mStartX:Int = 0
    private var mStartY:Int = 0
    override fun onTouch(view: View, event: MotionEvent): Boolean {
        val x = event.rawX.toInt()
        val y = event.rawY.toInt()
        when(event.action){
            MotionEvent.ACTION_DOWN -> {
                mStartX = x
                mStartY = y
                if (isPointChoice(x, y)) {
                    isCanMove = true
                }
            }
            MotionEvent.ACTION_MOVE -> {
                if (Math.abs(x - mStartX) < distance
                    && Math.abs(y - mStartY) < distance) {
                    if (mState == TouchState.STATE_STOP) {
                        return true
                        //break
                    }
                } else if (mState != TouchState.STATE_MOVE) {
                    mState = TouchState.STATE_MOVE
                }

                if(isCanMove){
                    updateLayoutParams(x, y)
                }

                mState = TouchState.STATE_MOVE
            }
            MotionEvent.ACTION_UP -> {
                isCanMove = false

                if (mState != TouchState.STATE_MOVE
                    && event.eventTime - event.downTime < MIN_TAP_TIME) {
                    setEventClick()
                }

                mState = TouchState.STATE_STOP
            }
        }

        return isCanMove
    }

    protected abstract fun setEventClick()

    private fun isPointChoice(x: Int, y: Int): Boolean {
        val cLocation = IntArray(2)
        childView?.getLocationOnScreen(cLocation)

        val horizontalMatch =
            x > (cLocation[0] + regionW) && x < (cLocation[0] + childWidth + regionW)
        val verticalMatch =
            y < (cLocation[1] + childHeight + DensityUtil.dip2px(context,10f)) && y > (cLocation[1] - regionW)

        if (horizontalMatch && verticalMatch) {
            return true
        }

        return false
    }
}

2.1,继承通用View

class DemoLineView(context: Context, attrs: AttributeSet?) : AbsParentDragView(context, attrs) {
    override fun setChildView(): View? {
        return LayoutInflater.from(context).inflate(R.layout.layout_draw_item, this, false)
    }

    override fun setChildInitLayoutParams(): LayoutParams {
        layoutParams.topMargin = DensityUtil.getScreenHeight(
            context
        ) - childHeight - DensityUtil.dip2px(context, 80f)
        layoutParams.leftMargin = DensityUtil.getScreenWidth(
            context
        ) - childWidth - DensityUtil.dip2px(context, 20f)
        return layoutParams
    }

    override fun setChildAction(childView: View?) {
        val tvSafeLine = childView?.findViewById<TextView>(R.id.tvSafeLine)
        tvSafeLine?.text = "设置悬浮"
    }

    override fun setEventClick() {
        Toast.makeText(context,"悬浮view",Toast.LENGTH_LONG).show()

    }

}

2.3,设计view的控制器

open class DragViewManager private constructor(context: Activity) {
    private var activity: Activity = context
    companion object : SingletonHolder<DragViewManager, Activity>(::DragViewManager)
    private lateinit var dragView: AbsParentDragView
    private val contentView = activity.window.decorView.findViewById<View>(android.R.id.content) as FrameLayout
    fun create(dragView: AbsParentDragView){
        this.dragView = dragView
        if(contentView.contains(dragView)){
            contentView.removeView(dragView)
        }
        contentView.addView(dragView)
    }
    fun show(){
        dragView.visibility = View.VISIBLE
    }
    fun dismiss(){
        dragView.visibility = View.INVISIBLE
    }
}

2.4,view的添加和使用

//创建出要显示的View
DragViewManager.getInstance(this).create(new DemoLineView(this,null));
//隐藏要显示的View
DragViewManager.getInstance(this).dismiss();
//显示要显示的View
DragViewManager.getInstance(this).show();

代码链接地址:gitee.com/component_i…

到此这篇关于Android Activity通用悬浮可拖拽View封装的文章就介绍到这了,更多相关Android Activity拖拽View封装内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android activity和view判断滑动

    Android activity和view判断滑动 实例代码: //手指按下的点为(x1, y1)手指离开屏幕的点为(x2, y2) float x1 = 0; float x2 = 0; float y1 = 0; float y2 = 0; @Override public boolean onTouchEvent(MotionEvent event) { //继承了Activity的onTouchEvent方法,直接监听点击事件 if(event.getAction() == Motion

  • Android新特性页面之ViewPager拖拽到最后一页再拖拽打开其他Activity(三种方法)

    android新特性页面,ViewPager拖拽到最后一页再拖拽打开其他Activity.实现的方式有很多,效果比较好的就是到了最后一页再拖拽出现禁止蓝色条时再跳转activity 方式一:拿到ViewPager的边界条EdgeEffectCompat,判断是否到了边界(获取EdgeEffectCompat通过反射,方法来自网络最后边会给出原文) /** * 初始化view */ private void initView(){ pager = (ViewPager) findViewById(

  • Android中通过view方式获取当前Activity的屏幕截图实现方法

    此方法是通过view的方式获取当前activity的屏幕截图,并不是framebuffer的方式,所以有一定的局限性.但是这种方法相对简单,容易理解. 首先通过下面的函数获取Bitmap格式的屏幕截图: 复制代码 代码如下: public Bitmap myShot(Activity activity) { // 获取windows中最顶层的view View view = activity.getWindow().getDecorView(); view.buildDrawingCache()

  • 详解如何在Android中实现悬浮Activity

    通常来说,为一款已经优化过的手机APP开发平板的版本也不是很难.使用Fragment.decompose Entities等组件就可以又快又轻松地完成.但是,最近遇到一个项目就没有这么简单了.我们不只要开发一个平板APP(基于ActionBarSherlock库,也称作ABS),还需要实现以下功能: 实现一个悬浮并且透明显示的Activity,这样用户在进行输入操作的时候可以看到别的Activity或者它自己的窗口背景: 保存悬浮的Activity的原始尺寸,包括水平方向和竖直方向:最好是Act

  • Android Activity通用悬浮可拖拽View封装的思路详解

    目录 1,背景 2,思路 2.1,封装通用的基础悬浮View 2.1,继承通用View 2.3,设计view的控制器 2.4,view的添加和使用 1,背景 在开发中总会遇到一个可拖拽的悬浮View,不管是在开发中,还是在线上,都时长有这样的控件,我们通常遇到这种情况,经常需要自己封装,需要耗费时间,我这边封装了一个可以通用的悬浮可拖拽View,这样使用的时候,只需要传入自己要设计的样式和位置既可 2,思路 2.1,封装通用的基础悬浮View 设计通用的父View 1,传入的childView是

  • 基于Vue实现可以拖拽的树形表格实例详解

    因业务需求,需要一个树形表格,并且支持拖拽排序,任意未知插入,github搜了下,真不到合适的,大部分树形表格都没有拖拽功能,所以决定自己实现一个.这里分享一下实现过程,项目源代码请看github,插件已打包封装好,发布到npm上 本博文会分为两部分,第一部分为使用方式,第二部分为实现方式 安装方式 npm i drag-tree-table --save-dev 使用方式 import dragTreeTable from 'drag-tree-table'  模版写法 <dragTreeTa

  • Android 实现抖音小游戏潜艇大挑战的思路详解

    <潜水艇大挑战>是抖音上的一款小游戏,以面部识别来驱动潜艇通过障碍物,最近特别火爆,相信很多人都玩过. 一时兴起自己用Android自定义View也撸了一个,发现只要有好的创意,不用高深的技术照样可以开发出好玩的应用.开发过程现拿出来与大家分享一下. 项目地址: https://github.com/vitaviva/ugame 基本思路 整个游戏视图可以分成三层: camera(相机):处理相机的preview以及人脸识别 background(后景):处理障碍物相关逻辑 foregroun

  • 微信小程序 实现拖拽事件监听实例详解

    微信小程序 拖拽监听功能: 在软件开发或者 APP应用开发的时候,经常会遇到拖拽监听,最近自己学习微信小程序的知识,就想实现这样的拖拽效果,这里就记录下. 需要做个浮在scroll-view之上的button.尝试了一下. 上GIF: Android中也会有类似移动控件的操作.思路差不多.获取到位移的X Y 的变量,给控件设置坐标. 1.index.wxml ../images/gundong.png" bindtap="ballClickEvent" style="

  • 完美实现js拖拽效果 return false用法详解

    本文为大家分享了完美实现js拖拽效果的具体代码,告诉大家return false的用法,供大家参考,具体内容如下 1.return false可以用来阻止默认事件即系统默认事件.例如通过阻止默认事件,来对textarea中的值进行范围限制(通过限制keycode的数值),也可以自定义在页面中的右键菜单(oncontextmenu). 2.在鼠标移动(mousemove)等事件中,是需要给事件传一个参数,保证程序的正常运行.而为了兼容取事件方法为:var oEvent=ev||event; 3.在

  • IOS 照片编辑的view封装的实例详解

    IOS 照片编辑的view封装 该控件有旋转,缩放,拖动,剪裁的功能,封装成了一个ImageCropperView类 需要导入的库:QuartzCore.framework ImageCopperView.h #import <UIKit/UIKit.h> @protocol ImageCropperDelegate; @interface ImageCropperView : UIView { UIImageView *imageView; id <ImageCropperDelega

  • Android实现悬浮可拖拽的Button

    本文实例为大家分享了Android实现悬浮可拖拽Button的具体代码,供大家参考,具体内容如下 1.简介 最近,因为项目需要,需要制作一个界面上可拖拽的按钮,网上也有多实例,看了下大部分都是示例不全或讲解不清晰,效果图也不明显,借此自己记录一番自己的实现方案,以备不时之需,同时也为广大学者可以直接通过拷贝方式完成项目所需. 2.效果图 在开始代码之前,首先看看效果图,如下: 3.核心代码实现 3.1 DraggingButton 实现 public class DraggingButton e

  • Android 自定义可拖拽View界面渲染刷新后不会自动回到起始位置

    以自定义ImageView为例: /** * 可拖拽ImageView * Created by admin on 2017/2/21. */ public class FloatingImageView extends ImageView{ public FloatingImageView(Context context) { super(context); } public FloatingImageView(Context context, AttributeSet attrs) { su

  • Android 在viewPager中双指缩放图片双击缩放图片单指拖拽图片的实现思路

    我们就把这个问题叫做图片查看器吧,它的主要功能有: 1.双击缩放图片. 2. 双指缩放图片. 3.单指拖拽图片. 为此这个图片查看器需要考虑以下的技术点: 一.双击缩放图片: 1.如果图片高度比屏幕的高度小得多,那么就将图片放大到高度与屏幕高度相等,否则就放大一个特定的倍数. 2.如何判断是否到达这个倍数来停止缩放. 3.判断完且停止放大后,图片可能已经超出了这个倍数需要的大小,如何回归到我们的目标大小. 4.判断完且停止缩小后,图片宽度可能已经小于屏幕宽度,在两边留下了空白,如何重置为原来的大

  • Android用RecyclerView实现图标拖拽排序以及增删管理

    1. 效果图 2. 基本的功能 在非编辑状态下可以直接点击图标进行跳转 在编辑状态可以拖拽.添加.删除操作 已被添加过的不能再次添加 3. 实现的思路 用两个RecyclerView实现,同时维护两个数据源,上部是常用应用,最多可以放8个:下部是全部应用. 1. 每个应用图标的状态用枚举Option表示 // 当前的操作状态 enum class Option { ADD, REMOVE, NONE } 2. 在处于编辑状态时创建ItemTouchHelper对象并attch到RecyclerV

随机推荐