
MeiWidgetView之RandomDragTagView小红书任意拖拽标签控件的完整实现思路【免费下载链接】MeiWidgetView一款汇总了郭霖鸿洋以及自己平时收集的自定义控件集合库小红书项目地址: https://gitcode.com/gh_mirrors/me/MeiWidgetViewMeiWidgetView 是一款 Android 自定义控件集合库其中的 RandomDragTagView 是一个仿小红书任意拖拽标签控件标签可以随手指在屏幕上自由拖动、贴边挤压变形、拖入删除区自动移除还能一键保存和恢复位置。本文将带你完整拆解它的实现思路新手也能看懂。️ 先看效果这个标签控件能做什么在 MeiWidgetView 的演示界面中一张图片上可以添加任意多个标签每个标签都具备以下能力自由拖拽按住标签随意拖动松手后若位置越界会自动回弹贴边挤压拖到屏幕左/右边缘时标签文本区域会被压扁而不是直接被裁掉方向随机标签文字可以出现在白色呼吸点的左侧或右侧点一下中间的小圆点即可切换呼吸灯动画标签中间的白点会持续放大缩小的呼吸效果更有生机拖拽删除把标签拖到底部 60dp 的红色删除区域再松手标签直接消失保存与恢复所有标签的位置、文本、方向可以序列化保存随时一键还原演示效果如下标签可随意拖动到图片任意位置 结构拆解一个标签由三部分组成每个标签本质上是一个水平排列的LinearLayout内部结构定义在布局文件 random_tag_layout.xml 中组成作用说明左侧标签承载文字图标 单行文本红色圆角背景中间呼吸点交互入口白色大圆点呼吸动画 红色小圆点点击可切换左右方向右侧标签承载文字与左侧完全镜像二者互斥显示标签创建时通过isShowLeftView参数随机决定文字显示在哪一侧模拟小红书标签左右都有的真实观感。核心实现都在 RandomDragTagView.java 这一个文件里。 小技巧呼吸灯用的是无限循环的ValueAnimator缩放 0.8 ↔ 1.0代码在startBreathingAnimator()方法RandomDragTagView.java。注意控件离开窗口时会调用clearBreathingAnimator()回收动画避免内存泄露——这是新手写自定义 View 时最容易踩的坑。✋ 拖拽实现四个关键机制1️⃣ 用 translation 移动而不是改变布局坐标拖动时不重新测量布局而是直接修改translationX / translationY这样性能最好、也最顺滑。移动逻辑集中在handlerMoveEvent()方法中RandomDragTagView.java每次 MOVE 事件计算与上次事件的坐标差值xDiff / yDiff累加到当前 translation 上得到新坐标做边界钳制x 限制在0 ~ 父容器宽-自身宽y 限制在0 ~ 最大高度2️⃣ 贴边挤压效果标签被压扁而不是裁切这是最出彩的细节。当标签贴住左边缘时继续往左拖文本区域会按比例变窄extrusionTextRegion()方法RandomDragTagView.java挤压下限mMaxExtrusionWidth默认 400px保证文字还能显示挤压上限初始完整宽度mMaxTextLayoutWidth回到中间时自动恢复左右两侧逻辑互为镜像——显示左侧标签时向右挤压显示右侧标签时向左挤压所以无论哪个方向都会压对边。3️⃣ 事件冲突处理让标签独占拖拽手势触摸冲突是拖拽控件的必考题。这里的处理很干脆ACTION_DOWN时调用getParent().requestDisallowInterceptTouchEvent(true)告诉父容器这次手势我自己处理ACTION_UP时恢复为false用mPointerDown标记多指按下第二根手指落下期间忽略 MOVE避免多点触控把标签甩飞4️⃣ 松手后的三种结局ACTION_UP时根据最终 y 坐标分三种情况RandomDragTagView.java松手位置结果进入底部 60dp 删除区removeTagView()直接从父容器移除标签删除越界超出父容器下边界触发startReBoundAnimator()回弹动画400ms 内平滑回到按下前的位置正常范围内原地停留并通知监听器onStopDrag()另外按下时还会调用adjustIndex()把当前标签移到子 View 的最顶层保证正在操作的标签永远盖住其他标签。 容器与 API三行代码添加一个标签单个标签由容器 RandomDragTagLayout.java继承自FrameLayout统一管理对外只暴露一个addTagView方法// 参数文本、x百分比(0~1)、y百分比(0~1)、是否显示左侧标签 mRandomDragTagLayout.addTagView(小红书标签, 0.3f, 0.5f, true);演示代码见 MeiRandomDragTagActivity.java用Random随机生成文本、位置和左右方向实现随机撒标签的效果。对应布局为 mei_drag_tag_activity.xml。 保存与恢复用百分比而非像素标签位置持久化是个隐藏亮点。RandomDragTagView提供了getPercentTransX() / getPercentTransY()返回的是相对父容器的百分比坐标而不是像素值。配合数据模型 TagModel.java含 x、y、文本、方向四个字段演示页的saveTag()会遍历所有子标签收集模型restoreTag()则按模型逐个重建MeiRandomDragTagActivity.java。 为什么要用百分比因为不同分辨率、不同屏幕方向下父容器尺寸会变像素坐标保存下来会错位百分比坐标天然适配任何屏幕。 相关源码路径清单文件说明RandomDragTagView.java标签核心拖拽、挤压、呼吸灯、回弹、删除RandomDragTagLayout.java标签容器提供 addTagView 入口TagModel.java标签数据模型用于保存/恢复random_tag_layout.xml标签 UI 结构定义random_tag_text_bg_selector.xml标签红底圆角背景MeiRandomDragTagActivity.java完整演示添加、保存、恢复✅ 小结新手能学到的三个通用技巧translation 移动 边界钳制是自定义拖拽控件的标配方案配合requestDisallowInterceptTouchEvent解决触摸冲突边界处改变自身尺寸挤压效果能显著提升交互质感比生硬裁切高级得多动画必须防内存泄露无限循环动画在onDetachedFromWindow中取消是自定义 View 的基本修养掌握这套思路后无论是做图片标注、弹幕挂件还是自由布局的贴纸都能快速迁移复用。【免费下载链接】MeiWidgetView一款汇总了郭霖鸿洋以及自己平时收集的自定义控件集合库小红书项目地址: https://gitcode.com/gh_mirrors/me/MeiWidgetView创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考