您现在的位置是:群英 > 开发技术 > 移动开发
Android实现可拖动的viewd怎样做,方法是什么
Admin发表于 2022-05-17 11:46:36886 次浏览
在实际案例的操作过程中,我们可能会遇到“Android实现可拖动的viewd怎样做,方法是什么”这样的问题,那么我们该如何处理和解决这样的情况呢?这篇小编就给大家总结了一些方法,具有一定的借鉴价值,希望对大家有所帮助,接下来就让小编带领大家一起了解看看吧。


业务来源

页面最小化后,需要出现一个浮动 view 告知用户,防止遮挡视线,需要对 view 做可滑动处理

已知会遇到的问题

1.view 的依赖的布局类型未知【为了后续方便扩展】

外界传递 viewgroup 自己本身继承 linearlayout【或者其他 viewgroup 】 

class floatchannelview(var mcontext: context?, var viewgroup: viewgroup) : linearlayout(mcontext){
    private var micon: imageview = imageview(context)
    private var mname: textview = textview(context)
    private var mclose: imageview = imageview(context)
    private var iconwh = dip2px(38)
    private var grouppadding = dip2px(3)
    private var mviewgrouph = dip2px(44)
    private var mviewgroupw = dip2px(152)
    private var mboundaryleft: float
    private var mboundarytop: float
    private var mboundaryright: float
    private var mboundarybottom: float
    private var mscreenwidth = getscreenwidth() // 获取屏幕宽高
    private var mscreenheight = getscreenheight()
 
    private var mdowneventx: float = 0f  // 相对控件的x
    private var mdowneventy: float = 0f
    private var mdownx: float = 0f  // 相对屏幕所在的 x
    private var mdowny: float = 0f
 
    private var mlistener: onclicklistener? = null
    private var misstartanimation: boolean = false
 
    private val mdefaultmargin = dip2px(12)
    private var mmarginleft = mdefaultmargin
    private var mmargintop = mdefaultmargin
    private var mmarginright = mdefaultmargin
    private var mmarginbottom = mdefaultmargin
 
    init {
        layoutparams = layoutparams(mviewgroupw, mviewgrouph)
        setpadding(grouppadding, grouppadding, grouppadding, grouppadding)
        setbackgroundresource(r.drawable.backage) // 建议加一些透明
        orientation = horizontal
        gravity = gravity.center_vertical
        mboundaryleft = mmarginleft.tofloat()
        mboundarytop = mmargintop.tofloat()
        mboundaryright = mscreenwidth - mmarginright.tofloat()
        mboundarybottom = (mscreenheight - mmarginbottom - dip2px(85)).tofloat()
        setview()
    }
}

2.拖动事件影响点击,事件分发处理。

override fun ontouchevent(event: motionevent?): boolean {
        if (misstartanimation) {  // 动画正在进行无需处理 ontouch
            return true
        }
        if (event == null) {
            return super.ontouchevent(event)
        }
        misontouch = true
        //悬浮区域左上角坐标
        val x = x
        val y = y
        //悬浮区域宽高
        val width = mviewgroupw
        val height = mviewgrouph
        when (event.actionmasked) {
            action_down -> {
                //点击位置坐标
                mdowneventx = event.x
                mdowneventy = event.y
                mdownx = x
                mdowny = y
            }
            action_up -> {
                muptime = system.currenttimemillis()
            
                if (mismove && abs(mdownx - x) <= 8f && abs(mdowny - y) <= 8f) {
                    mlistener?.onclick(this)
                }
                mismove = false
                // 抬起后处理边界溢出问题
                resilienceanimation(x, y, x + mviewgroupw, y + mviewgrouph)
            }
            action_move -> {
                val changex = event.x.toint() - mdowneventx
                val changey = event.y.toint() - mdowneventy
                mismove = true
                if (changex == 0f && changey == 0f) {
                    return super.ontouchevent(event)
                }
                val left = (x + changex).toint()
                val top = (y + changey).toint()
                val right = left + mviewgroupw
                val bottom = top + mviewgrouph
                layout(left, top, right, bottom)
            }
        }
        return true
    }

3.拖到边界问题。

拖出边界后做了回弹处理

/**
     *  超出边界回弹
     *  @param left 当前 x 方向位置
     *  @param right 当前 y 方向位置
*/
    private fun resilienceanimation(left: float, top: float, right: float, bottom: float) {
       
        var startx = 0f
        var resiliencex = 0f
        if (mboundaryleft <= left && right <= mboundaryright) {  // x 方向在范围内
            // 不处理
        } else if (mboundaryleft > left) {  // left 溢出
            startx = 0f
            resiliencex = mboundaryleft - left
        } else {   // right 方向底部溢出
            startx = 0f
            resiliencex = mboundaryright - right
        }
        var starty = 0f
        var resiliencey = 0f
        if (mboundarytop <= top && bottom <= mboundarybottom) {  // y 方向在范围内
            // 不处理
        } else if (mboundarytop > top) {  // top 溢出
            starty = 0f
            resiliencey = mboundarytop - top
        } else {  // bottom 溢出
            starty = 0f
            resiliencey = mboundarybottom - bottom
        }
        if (resiliencex == 0f && resiliencey == 0f) {  // 在范围内无需回弹
            return
        }
 
        // 超出边界回弹
        val phasefirstduration: long = 400
        var oanimphasefirsttupx: objectanimator? = null
        if (resiliencex != 0f) {
            oanimphasefirsttupx = objectanimator.offloat(this, "translationx", startx, resiliencex)
                    .setduration(phasefirstduration)
        }
        var oanimphasefirsttupy: objectanimator? = null
        if (resiliencey != 0f) {
            oanimphasefirsttupy = objectanimator.offloat(this, "translationy", starty, resiliencey)
                    .setduration(phasefirstduration)
        }
        val animatorset = animatorset()
        if (oanimphasefirsttupx != null && oanimphasefirsttupy != null) {
            animatorset.play(oanimphasefirsttupx).with(oanimphasefirsttupy)
        } else if (oanimphasefirsttupx != null) {
            animatorset.play(oanimphasefirsttupx)
        } else {
            animatorset.play(oanimphasefirsttupy)
        }
        animatorset.childanimations[animatorset.childanimations.size - 1].addlistener(object : animator.animatorlistener {
 
            override fun onanimationstart(animation: animator?) {
                misstartanimation = true
            }
 
            override fun onanimationend(animation: animator?) {
                var l = left
                var t = top
                var r = right
                var b = bottom
                when {
                    mboundaryleft > left -> {  // x左边溢出
                        l = mboundaryleft
                        r = mboundaryleft + mviewgroupw
                    }
                    mboundaryright < right -> {  // x右边溢出
                        l = mboundaryright - mviewgroupw
                        r = mboundaryright
                    }
                    else -> {  // x方向未溢出
                    }
                }
 
                when {
                    mboundarytop > top -> {  // y 顶部溢出
                        t = mboundarytop
                        b = mboundarytop + mviewgrouph
                    }
                    mboundarybottom < bottom -> {  // y 底部溢出
                        t = mboundarybottom - mviewgrouph
                        b = mboundarybottom
                    }
                    else -> {  // y方向未溢出
                    }
                }
                // 只进行偏移,实际位置未变化,需要重置偏移量,并重绘
                this@floatchannelview.translationx = 0f
                this@floatchannelview.translationy = 0f
                layout(l.toint(), t.toint(), r.toint(), b.toint())
                mmarginleft = l.toint()
                mmargintop = t.toint()
                misstartanimation = false
            }
 
            override fun onanimationcancel(animation: animator?) {}
 
            override fun onanimationrepeat(animation: animator?) {}
 
        })
        animatorset.start()

感谢各位的阅读,以上就是“Android实现可拖动的viewd怎样做,方法是什么”的内容了,通过以上内容的阐述,相信大家对Android实现可拖动的viewd怎样做,方法是什么已经有了进一步的了解,如果想要了解更多相关的内容,欢迎关注群英网络,群英网络将为大家推送更多相关知识点的文章。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: 可拖动的view
相关信息推荐
2022-08-19 17:50:24 
摘要:CART算法是一种树构建算法,既可以用于分类任务,又可以用于回归,本文仅讨论基本的CART分类决策树构建,不讨论回归树和剪枝等问题,感兴趣的朋友跟随小编一起看看吧
2022-05-07 17:29:58 
摘要:在PHP中,可以利用“openssl_encrypt()”函数实现aes加密,只需要将参数中加密方法设置为“AES-128-ECB”即可,语法为“openssl_decrypt(加密明文,'AES-128-ECB',加密密钥,数据格式)”。
2022-07-30 17:36:40 
摘要:两种检测方法:1、使用in_array函数检测,可以查找数组中是否包含指定类型的值,语法“in_array('字符串',数组,true)”,如果返回值为TRUE则包含,反之则不包含。2、使用array_search()函数检测,可以查找数组中是否包含指定类型的值,语法“array_search('字符串',数组,true)”,如果返回对应键名则包含,如果返回FALSE则不包含。
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部