Android(Java):基于后端坐标在图片上绘制可点击矩形/正方形
Android自定义View实现可点击的动态矩形绘制
我从后端获取了一组坐标,需要在Android(Java)应用中依据这些坐标在图片上绘制矩形或正方形,且绘制的图形需支持点击操作。以下是我当前实现的自定义View代码:
public class DrawView extends View { Paint paint = new Paint(); private void init() { paint.setColor(Color.BLACK); } public DrawView(Context context) { super(context); init(); } public DrawView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DrawView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } @Override public void onDraw(Canvas canvas) { canvas.drawRoundRect(150,150,300,300,10,10,paint); canvas.drawRect(300, 300, 600, 600,paint); } }
解决方案
1. 创建矩形数据模型类
定义模型类封装矩形的坐标、样式和点击逻辑:
public class RectItem { private float left; private float top; private float right; private float bottom; private boolean isRound; private float roundRadiusX; private float roundRadiusY; private int color; private OnRectClickListener listener; public RectItem(float left, float top, float right, float bottom, boolean isRound, float roundRadiusX, float roundRadiusY, int color) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; this.isRound = isRound; this.roundRadiusX = roundRadiusX; this.roundRadiusY = roundRadiusY; this.color = color; } public float getLeft() { return left; } public float getTop() { return top; } public float getRight() { return right; } public float getBottom() { return bottom; } public boolean isRound() { return isRound; } public float getRoundRadiusX() { return roundRadiusX; } public float getRoundRadiusY() { return roundRadiusY; } public int getColor() { return color; } public void setListener(OnRectClickListener listener) { this.listener = listener; } public boolean contains(float x, float y) { return x >= left && x <= right && y >= top && y <= bottom; } public void performClick() { if (listener != null) { listener.onRectClick(this); } } public interface OnRectClickListener { void onRectClick(RectItem rectItem); } }
2. 改造自定义View支持动态绘制与点击
更新DrawView类,添加数据集合、绘制逻辑和触摸事件处理:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import java.util.ArrayList; import java.util.List; public class DrawView extends View { private Paint mPaint; private List<RectItem> mRectList; private RectF mTempRectF; private void init() { mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(5); mRectList = new ArrayList<>(); mTempRectF = new RectF(); } public DrawView(Context context) { super(context); init(); } public DrawView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DrawView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public void addRectItem(RectItem rectItem) { mRectList.add(rectItem); invalidate(); } public void setRectList(List<RectItem> rectList) { mRectList.clear(); if (rectList != null) { mRectList.addAll(rectList); } invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 如需绘制背景图片,在此处添加canvas.drawBitmap(...)逻辑 for (RectItem item : mRectList) { mPaint.setColor(item.getColor()); if (item.isRound()) { mTempRectF.set(item.getLeft(), item.getTop(), item.getRight(), item.getBottom()); canvas.drawRoundRect(mTempRectF, item.getRoundRadiusX(), item.getRoundRadiusY(), mPaint); } else { canvas.drawRect(item.getLeft(), item.getTop(), item.getRight(), item.getBottom(), mPaint); } } } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { float x = event.getX(); float y = event.getY(); // 倒序遍历确保上层矩形优先响应点击 for (int i = mRectList.size() - 1; i >= 0; i--) { RectItem item = mRectList.get(i); if (item.contains(x, y)) { item.performClick(); return true; } } } return super.onTouchEvent(event); } }
3. 在Activity中使用自定义View
布局文件中添加DrawView:
<com.yourpackage.DrawView android:id="@+id/drawView" android:layout_width="match_parent" android:layout_height="match_parent"/>
Activity中初始化数据并设置点击回调:
import android.os.Bundle; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DrawView drawView = findViewById(R.id.drawView); List<RectItem> rectList = new ArrayList<>(); // 添加圆角矩形 RectItem roundRect = new RectItem(150, 150, 300, 300, true, 10, 10, Color.BLACK); roundRect.setListener(item -> Toast.makeText(MainActivity.this, "点击了圆角矩形", Toast.LENGTH_SHORT).show()); rectList.add(roundRect); // 添加普通矩形 RectItem normalRect = new RectItem(300, 300, 600, 600, false, 0, 0, Color.BLACK); normalRect.setListener(item -> Toast.makeText(MainActivity.this, "点击了普通矩形", Toast.LENGTH_SHORT).show()); rectList.add(normalRect); drawView.setRectList(rectList); } }
关键说明
- 数据模型
RectItem统一管理矩形的属性与点击行为,便于维护和扩展 - 使用复用的
RectF对象避免onDraw中频繁创建对象,优化绘制性能 - 倒序遍历矩形列表,确保视觉上层的矩形优先响应点击,符合交互逻辑
内容的提问来源于stack exchange,提问作者Mohit Chaudhary
相关产品推荐
相关产品推荐

