浮在页面上可拖动的View

本文介绍了一个可拖动并随页面滑动自动隐藏或显示的浮动视图组件。该组件支持多种布局,并能根据可滑动视图的滚动状态自动调整位置。

一、概述

转眼到2022年了,回想第一次在csdn上写东西是2017年,距现在已过去5年。这5年之间,身边的人有的结婚了,有的生小孩了,有的买房了,有的升级做管理不再写代码了。而我,与这些都没有关系,还是一个菜,只不过从一个小菜变成了一个老菜,功不成名不就。
既然已经是这样,多说和感慨也无法改变,不如做好手下的事吧!

去年在项目中写过一个浮在页面上随手指拖动的View,因为需要在很多页面用到,所以封装了一下,感觉还是有点必要记录一下,方便自己日后再次使用,也希望能给有类似需求的你提供参考,当然这并不是很难实现。

效果是这样:
1、浮在页面上,可以随手指拖动;
2、手指释放后,缓慢平移到距离最近的页面边缘;
3、页面上滑时,会缩到页面边缘里面;下滑时,会伸出来。
看效果图:
在这里插入图片描述

二、代码实现

FloatDragView不是继承View,要显示的floatView通过构造方法中传入。里面封装了实现逻辑:
1、先将floatView添加到父View中,根据父View的类型,设置layoutParams,放置在右下角;
2、给floatView设置OnTouchListener,手指移动时,计算出x、y的位移,再检查边界后(不能滑出父View),改变translationX、translationY实现移动(原本使用offsetLeftAndRight、offsetTopAndBottom,但发现有些许问题);手指释放时,计算距离屏幕最近的水平值,通过动画移动到边缘;
3、监听可滑动的view,滑动时移动到相应位置,达到缩起和伸出效果。

下面上代码:

class FloatDragView(private var floatView: View?) {
   
   

    private val touchSlop by lazy(LazyThreadSafetyMode.NONE) {
   
   
        val context = floatView?.context
        if (context != null)
            ViewConfiguration.get(context).scaledTouchSlop
        else
            0
    }

    private var parentView: ViewGroup? = null//floatView的父View
    private var scrollView: View? = null//可滑动的view,根据他的滑动来折叠和弹出floatView
    private var clickAction: ((View) -> Unit)? = null
    private var isAnimatorRunning = false//是否在执行动画
    private var isCollapse = false//是否已折叠
    private var collapseWidth = 0f//折叠的宽度
    private var rightMargin = 0//左边margin

    private var isDragStatus = false//floatView是否是拖动状态
    private var isOnTheRight = true//floatView是否在右边,true在右边,false在左边

    /**
     * 将floatView加到父view中
     * parentView: 父view
     * canScrollView: 可滑动的view,根据它上下滑动收起和展开floatView。为空时不会有收起展开功能
     * clickAction: floatView点击事件
     */
    fun attach(
        parentView: ViewGroup, canScrollView: View? = null,
        clickAction: ((View) -> Unit)? = null
    ) {
   
   
        this.scrollView = canScrollView
        this.parentView = parentView
        this.clickAction = clickAction
        addFloatView()
    }

    /**
     * 移除floatView
     */
    fun removeFloatView() {
   
   
        parentView?.removeView(floatView)
        floatView = null
    }

    /**
     * 设置floatView的可见性
     */
    fun setVisibility(visibility: Int) {
   
   
        floatView?.visibility = visibility
    }

    /**
     * 执行添加floatView操作,设置相关监听
     */
    private fun addFloatView() {
   
   
        val contentView = parentView ?: return
        val floatView = floatView ?: return
        if (floatView.parent != null) {
   
   
            contentView.removeView(floatView)
        }
        val context = contentView.context
        floatView.setOnClickListener {
   
   
            if (isCollapse) {
   
   
                floatOut()
            } else {
   
   
                clickAction?.invoke(it)
            }
        }
        setupDrag(floatView)
        val resource = context.resources
        val width = resource.getDimensionPixelSize(R.dimen.dp_56)
        val height = resource.getDimensionPixelSize(R.dimen.dp_44)
        rightMargin = resource.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值