Android自定义视图不会#39;要多次绘制

时间:2015-02-23 11:02:34

标签: android view draw

我在绘制时添加了一个标记(init),在View Creation上创建了一个100x500矩形,但是当我从onTouch方法绘制testDraw方法时,没有任何东西被绘制出来。

DrawingView

class DrawingView extends View{
    Canvas canvas= new Canvas();;
    Paint paint= new Paint();
    boolean init;
    public DrawingView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        paint.setColor(Color.argb(255, 0, 255, 0));

        this.init = true;
    }

    public void testDraw(){
        canvas.drawRect(0,0,500,500,paint);
    }

    @Override
    public void onDraw(Canvas canvas){
        if(this.init == true){
            canvas.drawRect(0,0,500,100,paint);
            this.init = false;
        }else{
        }

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            testDraw();
        }
        return false;
    }


}

4 个答案:

答案 0 :(得分:1)

这是因为您正在绘制到不同的画布,然后是屏幕上显示的画布。

重新绘制视图的正确方法是使其无效,如下所示:

private boolean testDrawn = false;

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN) {
        testDrawn = true;
        invalidate(); // << this will make on drawn be called again
    }
    return false;
}

然后在绘制方法

   @Override
    public void onDraw(Canvas canvas){
        if(this.init == true){
            canvas.drawRect(0,0,500,100,paint);
            this.init = false;
        }else if(testDrawn){
            testDrawn = false;
            // do the drawing here ...
        }
    }

并删除此行Canvas canvas= new Canvas();该视图不应拥有自己的画布。

答案 1 :(得分:0)

建议:你应该保留画布的引用,以便能够在 onDraw发生之后处理它,如下所示:

class DrawingView extends View{
    Canvas your_canvas= new Canvas(); /* change the variable name */
    Paint paint= new Paint();
    boolean init;
    public DrawingView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        paint.setColor(Color.argb(255, 0, 255, 0));

        this.init = true;
    }

    public void testDraw(){
        your_canvas.drawRect(0,0,500,500,paint); /* changed variable name */
    }

    @Override
    public void onDraw(Canvas canvas){
        if(this.init == true){
            your_canvas = canvas; /* keep canvas reference in your_canvas variable */
            canvas.drawRect(0,0,500,100,paint);
            this.init = false;
        }else{
        }

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            testDraw();
        }
        return false;
    }


}
编辑:根据@Budius你不应该这样做...所以也许调用View.invalidate()方法可以重新加载onDraw,然后做你需要的(?)

答案 2 :(得分:0)

来自SDK Documentation

onTouch() - 返回一个布尔值,指示您的侦听器是否使用此事件。重要的是这个事件可以有多个相互跟随的动作。因此,如果在收到向下操作事件时返回false,则表示您尚未使用该事件,并且对此事件的后续操作也不感兴趣。因此,您不会在事件中调用任何其他操作,例如手指手势或最终的上行动作事件。 触发ACTION_DOWN事件时,您需要返回true,以指示您对与该同一事件相关的后续调用感兴趣。

我认为问题在于您从onTouch返回false,这意味着您对此事件以及与之相关的后续操作不感兴趣。所以我建议从这里回复。

答案 3 :(得分:0)

试试这个,这是一个有效的例子,如果你在画布上绘制任何东西,你应该调用invalidate()方法,使视图重绘,testDraw方法中的画布也不与视图相关,你应该使用onDraw参数中的画布,或者为它创建一个特殊的位图

public class DrawingView extends View {
private Bitmap cachedBitmap;
private Canvas cachedCanvas;
private Paint linePaint;

private boolean isClicked;
private float lastX;
private float lastY;

public DrawingView(Context context) {
    super(context);
}

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

public DrawingView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onDraw(Canvas canvas) {
    int width = getWidth();
    int height = getHeight();
    if(cachedBitmap == null && width > 0 && height > 0) {
        cachedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        cachedCanvas = new Canvas(cachedBitmap);
        linePaint = new Paint();
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(3);
        linePaint.setColor(Color.parseColor("#000000"));
    }
    canvas.drawBitmap(cachedBitmap, 0, 0, null);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            isClicked = true;
            break;

        case MotionEvent.ACTION_MOVE:
            if(isClicked && cachedCanvas != null) {
                cachedCanvas.drawLine(lastX, lastY, event.getX(), event.getY(), linePaint);
                invalidate();
            }
            break;

        case MotionEvent.ACTION_UP:
            isClicked = false;
            break;
    }
    lastX = event.getX();
    lastY = event.getY();
    return true;
}

}