android怎么实现可拖动的浮动view
发表于:2025-11-10 作者:千家信息网编辑
千家信息网最后更新 2025年11月10日,本篇内容主要讲解"android怎么实现可拖动的浮动view",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"android怎么实现可拖动的浮动view"吧!
千家信息网最后更新 2025年11月10日android怎么实现可拖动的浮动view
本篇内容主要讲解"android怎么实现可拖动的浮动view",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"android怎么实现可拖动的浮动view"吧!
业务来源
页面最小化后,需要出现一个浮动 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 privateval 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怎么实现可拖动的浮动view"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
方向
浮动
位置
边界
处理
事件
内容
区域
坐标
实际
屏幕
底部
问题
偏移
学习
实用
更深
最小
业务
兴趣
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
浪潮服务器自动化生产线解决方案
中国网络安全法律缺失
qq运动同步数据库
网络安全病毒的特点包括
广东网络技术服务哪家好
计算机网络技术三级考啥
学会编程软件开发
最终幻想14最新服务器
智慧服务中心软件开发部
数据库技术课程有些什么
数据库采集与分析
查看已创建的数据库字符集的命令
软件开发公司信任 云趣科技
数据库是excel的功能吗
数据库引擎配置
社交直播软件开发
语音服务器超时怎么回事
战争雷霆正在连接服务器
聊城戴尔服务器代理零售
杭州软件开发正规平台
网易我的世界失落世界服务器在哪
党员干部网络安全行为准则
网络安全部长是谁
服务器 hyper-v
财务软件主服务器互联网
软件开发公司信任 云趣科技
数据库学习的英文书
数据库是excel的功能吗
马化腾网络安全系统
商洛软件开发行业标准