【问题标题】:Draw a circle in Android Canvas when previous circle was selected at predefined positions当在预定义位置选择上一个圆圈时,在 Android Canvas 中绘制一个圆圈
【发布时间】:2016-01-08 13:56:45
【问题描述】:

这是我第一次在 Android 中使用 Canvas。 我正在创建一个应用程序,该应用程序将在屏幕上的某些位置一次显示一个圆圈(位置是随机选择的)。选择/触摸前一个圆圈后应绘制新圆圈,前一个圆圈应消失。 我对此有一些想法:保留一个 Point 对象的数组列表(每个对象包含圆心的 x,y 坐标),并在每次在屏幕上绘制圆时随机选择一个。所以首先我要填充一个点数组。我也知道如何从 arraylist 中随机选择元素。 我最大的困惑是如何将 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));
    }

}

【问题讨论】:

    标签: java android canvas touch-event ondraw


    【解决方案1】:

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

    如果有人需要参考,这是我的解决方案

    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));
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      类变量

      private int state = 0     //0 normal, 1 new circle
      private int pointPos = 0; //Which point we will be drawing
      

      onDraw 覆盖了你所有其他点的 x/y

      @Override
      protected void onDraw(Canvas canvas) {
          super.onDraw(canvas);
      
      
          paint.setStyle(Paint.Style.STROKE);
          canvas.drawColor(Color.WHITE);
      
          if(state == 1){
              pointPos = random(); //between 0 and points.length
              state = 0;
          }
      
          canvas.drawCircle(points.get(pointsPos).x, points.get(pointsPos).y, 50, paint);
      
      }
      

      onTouchEvent:绘图只应在 ondraw 上完成,使用标志/状态来跟踪您在下一次绘图调用时应该做什么

      @Override
      public boolean onTouchEvent(MotionEvent event) {
          switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN:
      
                  //Though these days this is usually done on the up event
                  //Check if the point press is within the circle
                  if(contains(event, points.get(pointPos))){
                      state = 1;
                      postInvalidate();
                  }
      
      
      
              case MotionEvent.ACTION_MOVE:
              case MotionEvent.ACTION_UP:
              case MotionEvent.ACTION_CANCEL: {
                  break;
              }
          }
          postInvalidate();
          return true;
      
      }
      

      【讨论】:

      • 亲爱的 Chris Handy,非常感谢您的回答!它现在工作正常!对于那些和我有同样问题的人,一旦我开始工作,我会稍后更新代码
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      • 1970-01-01
      • 2013-10-02
      • 2014-09-25
      • 2013-09-20
      • 2012-11-12
      相关资源
      最近更新 更多