java - 当在预定义位置选择上一个圆时,在 Android Canvas 中绘制一个圆

标签 java android canvas touch-event ondraw

这是我第一次在 Android 中使用 Canvas。 我正在创建一个应用程序,它会在屏幕上的某些位置一次显示一个圆圈(位置是随机选择的)。选择/触摸前一个圆圈后应绘制新圆圈,并且前一个圆圈应消失。 我对此有一些想法:保留一个 Point 对象的数组列表(每个对象包含圆心的 x,y 坐标),并在每次在屏幕上绘制圆时随机选择一个。所以首先我要填充一个点数组。我还知道如何从数组列表中随机选择元素。 我最大的困惑是如何将 onDraw 和 onTouchEvent 方法相互连接?我知道我应该检查是否选择了圆圈,然后才在随机选择的位置绘制一个新圆圈,但我不确定如何从 onTouchEvent 调用 onDraw() 方法...

您能帮忙解决这个问题吗? 我的代码如下:

package com.example.researcher.heatmap;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * TODO: document your custom view class.
 */
public class MyView extends View {

    Paint paint;
    ArrayList<Point> points = new ArrayList<>();



    public MyView(Context context) {
        super(context);
        init();
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        // Load attributes
        paint = new Paint();
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(5);
        paint.setStyle(Paint.Style.STROKE);
        populateArrayList();

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        paint.setStyle(Paint.Style.STROKE);
            canvas.drawColor(Color.WHITE);
            int i=1; // should be random, will randomize later

            for(Point p: points) {
                p.x = points.get(i).x;
                p.y = points.get(i).y;

                canvas.drawCircle(p.x, p.y, 50, paint);
            }

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:


                int i=1;

                for(Point p: points) {
                    Canvas canvas = new Canvas();
                    p.x = points.get(i).x;
                    p.y = points.get(i).y;
                    canvas.drawCircle(p.x, p.y, 50, paint);
                }

                postInvalidate();

            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL: {
                break;
            }
        }
        postInvalidate();
        return true;

    }

    public void populateArrayList(){
        points.clear();
        points.add(new Point(120, 120));
        points.add(new Point(150, 320));
        points.add(new Point(280, 200));
    }

}

最佳答案

谢谢克里斯的帮助!对此,我真的非常感激。

这是我的解决方案,如果有人需要引用

package com.example.researcher.heatmap;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * TODO: document your custom view class.
 */
public class MyView extends View {

    Paint paint;
    ArrayList<Point> points = new ArrayList<>();
    private int pointsPos = 0; //Which point we will be drawing
    public float x;
    public float y;
    public int radius = 150;



    public MyView(Context context) {
        super(context);
        x = this.getX();
        y = this.getY();
        init();
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        x = this.getX();
        y = this.getY();
        init();
    }

    public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        x = this.getX();
        y = this.getY();
        init();
    }

    private void init() {
        // Load attributes
        paint = new Paint();
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(5);
        paint.setStyle(Paint.Style.STROKE);
        populateArrayList();

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        paint.setStyle(Paint.Style.STROKE);
        canvas.drawColor(Color.WHITE);

        canvas.drawCircle(points.get(pointsPos).x, points.get(pointsPos).y, radius, paint);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:

            case MotionEvent.ACTION_UP:
                //Check if the point press is within the circle
                if(contains(event, points.get(pointsPos))){

                    Random r = new Random(System.nanoTime());
                    pointsPos = r.nextInt(points.size());; //between 0 and points.length

                    postInvalidate();
                }


            case MotionEvent.ACTION_CANCEL: {
                break;
            }
        }
        postInvalidate();
        return true;

    }

    private boolean contains(MotionEvent event, Point point) {
        float xTouch = event.getX();
        float yTouch = event.getY();
        if ((xTouch - point.x) * (xTouch - point.x) + (yTouch - point.y) * (yTouch - point.y) <= radius * radius) {
            return true;
        }
        else {
            return false;
        }
    }

    public void populateArrayList(){
        points.clear();
        points.add(new Point(220, 1020));
        points.add(new Point(550, 320));
        points.add(new Point(780, 500));
    }

}

关于java - 当在预定义位置选择上一个圆时,在 Android Canvas 中绘制一个圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34678775/

相关文章:

java - 如何告诉 Spring 在不提供构造函数参数的情况下实例化选定的 bean?

java - 如何在 java 中调用用 kotlin 类编写的函数?

android - Android 2.2 中无预览的相机捕获

java - 按元素对两个数组求和,携带 1 时出现问题

java - Spring Boot - 从 application.yml 注入(inject)静态映射

java - 警告 : [path] the output directory is within an exploded module java 9

java - Android 异步任务 ArrayList 操作导致 onDraw 中 IndexOutOfBounds

javascript - 如何删除 fabric.js 中的绘图?

javascript - HTML5 Canvas 2D 相机并且只在屏幕上渲染内容?

javascript - Highcharts 到图像