如何监听自定义控件onClick事件,实现选中图形移动及GradientDrawable.RingShape显示
1. 选中对象移动功能实现
核心改动点:
- 给Dot类增加选中状态回调,和Activity的selectedCompound联动
修改Dot类构造:
open class Dot( context: Context, val parent: RelativeLayout, var x: Int, var y: Int, private val onSelectStateChanged: (Dot, Boolean) -> Unit ) : View(context), Graphic, View.OnClickListener { // 原有代码不变 override fun onClick(v: View?) { isClicked = !isClicked dotDrawable.setColor(if(isClicked) Color.RED else Color.BLACK) // 通知上层选中状态变更 onSelectStateChanged.invoke(this, isClicked) } }
Circle类构造同步加回调参数:
class Circle( context: Context, parent: RelativeLayout, x: Int, y: Int, var radius: Int, onSelectStateChanged: (Dot, Boolean) -> Unit ) : Dot(context, parent, x, y, onSelectStateChanged) { // 原有代码不变 }
- Activity中初始化图形时绑定回调,维护selectedCompound
// 初始化Dot示例 val dot = Dot(this, parent, 100, 100) { graphic, isSelected -> if (isSelected) { selectedCompound.add(graphic) } else { selectedCompound.remove(graphic) } } // Circle和其他图形初始化逻辑同理
- 修改移动按钮逻辑,支持选中对象移动
以下为优先移动选中对象的逻辑,也可自行增加切换按钮分别控制移动全部/选中对象:
moveButton.setOnClickListener { val x = xField.text.toString().toIntOrNull() ?: 0 val y = yField.text.toString().toIntOrNull() ?: 0 if (selectedCompound.children.isNotEmpty()) { selectedCompound.move(x, y) } else { allCompound.move(x, y) } }
2. GradientDrawable RingShape不显示问题解决
之前设置不生效是因为Ring类型必须主动设置尺寸,正确实现代码如下:
val ringDrawable = GradientDrawable().apply { shape = GradientDrawable.RING setColor(Color.TRANSPARENT) // 内部填充透明 setStroke(20, Color.BLACK) // 环描边颜色、宽度 innerRadiusRatio = 2f // 内半径 = 总宽度 / innerRadiusRatio,数值越大内半径越小 thicknessRatio = 4f // 环厚度 = 总宽度 / thicknessRatio,数值越大环越细 setSize(400, 400) // 必须设置固定尺寸,否则默认宽高为0无法显示 }
3. 组合模式演示优化建议
- 解耦平台逻辑:把Graphic接口做成纯业务抽象,不继承Android View、不持有Context,单独抽渲染层负责Android端绘制,核心组合逻辑和平台无关,更能突出设计模式本身的结构。
- 消除重复代码:Dot和Circle的move逻辑高度重复,可以把LayoutParams抽到父类作为open变量,move逻辑统一在父类实现,子类只需要修改对应LayoutParams参数即可。
- 优化移动性能:移动时不需要反复removeView+addView,直接修改LayoutParams的margin值后调用
requestLayout()即可,渲染效率更高。 - 支持组合选中:给Graphic接口增加isSelected属性,CompoundGraphic实现选中逻辑时可以递归处理子元素的选中状态,实现“选中整个组合、移动整个组合”的特性,完全贴合组合模式单个对象和组合对象使用一致的核心设计。

内容的提问来源于stack exchange,提问作者Nero Nguyen
相关产品推荐
相关产品推荐

