为什么没有为我设置OnTouchListener?

时间:2015-10-03 02:19:38

标签: java android drawing ontouchlistener

我正在处理名为CanvasView的自定义视图。这是一个允许我在onDraw方法之外绘制内容的视图。它是这样的:

public class CanvasView extends View {
    private ArrayList<Shape> shapes;
    private Paint paint;

    public CanvasView (Context c) {
        super(c);
        init ();
    }

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

    public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super (context, attrs, defStyleAttr);
        init ();
    }
    private void init () {
        shapes = new ArrayList<> ();
        paint = new Paint ();
        paint.setStrokeWidth (5);
        paint.setColor (Color.BLACK);
    }

    //focus on this method, I think the others are irrelevant
    @Override
    public void setOnTouchListener (final OnTouchListener listener) {
        final OnTouchListener baseListener = new OnTouchListener () {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                float x = event.getX ();
                float y = event.getY ();
                if (x < 18 || x > getWidth () - 18 || y < 18 ||
                        y > getHeight () - 18)
                    return false;

                return true;
            }
        };

        super.setOnTouchListener (new OnTouchListener () {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (baseListener.onTouch (v, event)) {
                    if (listener != null) {
                        return listener.onTouch (v, event);
                    } else {
                        return true;
                    }
                }
                return false;
            }
        });
    }

    @Override
    protected void onDraw (Canvas c) {
        super.onDraw (c);
        for (Shape s : shapes) {
            s.draw (c);
        }
        //draw the border. irrelevant
        c.drawLine (3, 3, getWidth () - 3, 3, paint);
        c.drawLine (3, getHeight () - 3, getWidth () - 3, getHeight () - 3, paint);
        c.drawLine (3, 3, 3, getHeight () - 3, paint);
        c.drawLine (getWidth () - 3, 3, getWidth () - 3, getHeight () - 3, paint);

        //draw the inner border
        c.drawLine (18, 18, getWidth () - 18, 18, paint);
        c.drawLine (18, getHeight () - 18, getWidth () - 18, getHeight () - 18, paint);
        c.drawLine (18, 18, 18, getHeight () - 18, paint);
        c.drawLine (getWidth () - 18, 18, getWidth () - 18, getHeight () - 18, paint);
    }

    public void addShape (Shape s) {
        shapes.add (s);
    }

    public void clear () {
        shapes.clear ();
    }
}

说明:

Shape是一个方法接口:

public void draw (Canvas c);

专注于setOnTouchListener覆盖。我重写了这种方法,因为我想限制用户不要触摸CanvasView的边框。如您所见,我首先调用baseListener来检查触摸是否在边界内。然后我调用构造函数中传递的侦听器。这是一个好习惯吗?

无论如何,我在OnTouchListener方法中设置CanvasView的{​​{1}}:

onCreate

说明:

canvas.setOnTouchListener (new View.OnTouchListener () { @Override public boolean onTouch(View v, final MotionEvent event) { if (point1 != null && point2 != null) { throw new IllegalStateException ("Both point1 and point2 are not null"); } if (point1 == null) { point1 = new PointF (event.getX (), event.getY ()); } else { //point2 is null point2 = new PointF (event.getX (), event.getY ()); canvas.addShape (new Shape () { @Override public void draw(Canvas c) { c.drawLine (point1.x, point1.y, point2.x, point2.y, paint); } }); canvas.setOnTouchListener (null); } canvas.addShape (new Shape () { @Override public void draw(Canvas c) { c.drawCircle (event.getX (), event.getY (), 13, paint); } }); return true; } }); point1是在活动类中声明的字段。当用户触摸屏幕时,其中一个将被实例化并且在该点处绘制一个小圆圈。当用户第二次触摸时,实例化point2并在两点之间绘制一条线。

当我运行我的应用程序并触摸屏幕时,没有任何内容被绘制!我认为point2覆盖未正确写入。谁能告诉我为什么?

1 个答案:

答案 0 :(得分:1)

只有在首次创建视图时才会调用View的onDraw方法。要使其再次被调用,每次视图内容发生更改时,您需要使用视图上的invalidate()函数将视图标记为“脏”(已进行更改)。

因此,在addShape函数中向视图添加形状之后,可以方便地调用此函数。

 public void addShape (Shape s) {
        shapes.add (s);
        this.invalidate();
    }