1

这是我第一次在这里提问。我的安卓应用程序有这个问题。我想在我的自定义视图类中创建不同的绘制方法。三个按钮对应3种不同的形状。当按下按钮时,它将绘制其形状。但是当我尝试从 MainActivity 调用自定义绘图让我测试它时,应用程序崩溃了。

主要活动

import com.example.shapes.view.ShapesView;

public class MainActivity extends Activity {

ShapesView shapesview;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    shapesview = (ShapesView) findViewById(R.id.ShapesViewID);
    shapesview.DrawRectangle();
}

形状视图

public class ShapesView extends View{

Canvas canvas;

public ShapesView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}

@Override
protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    this.canvas = canvas;
}

public void DrawRectangle() {
    Paint mypaint = new Paint();
    mypaint.setColor(Color.BLUE);
    canvas.drawRect(30, 30, 200, 200, mypaint);
}
}

我的 XML 布局文件

<com.example.shapes.view.ShapesView android:id="@+id/ShapesViewID" android:layout_width="fill_parent" android:layout_height="fill_parent" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />`

请帮忙!非常感谢!

4

4 回答 4

2

If I understand your question you need a custom view (a button) which will draw itself differently based on some event. If that is the case then you need to respect the android's guidelines about the view drawing take a look here.

Now one possible solution for your case is to set some kind of flag about the state of your view and then use that flag when you are ready to draw. For example you can do this:

public class ShapesView extends View{

public int state = 0;

public ShapesView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (state == 1) {
    Paint mypaint = new Paint();
    mypaint.setColor(Color.BLUE);
    canvas.drawRect(30, 30, 200, 200, mypaint);
}
}

and then whenever you need to draw your view from an activity you can use the following:

myview.state = 1;
myview.invalidate();

In your code what you are doing is that you call a views function during the onCreate of your activity which in turn tries to use a null canvas because the onDraw method of your view has not be called during that time. Furthermore as others have pointed out you must not use a canvas object outside the onDraw method.

Hope this helps...

于 2013-07-11T15:26:51.690 回答
1

查看方法的名称 itonDraw()而不是getCanvas()。该文档也没有对所Canvas提供的内容提出任何声明。

完成后onDraw()canvas可能会被丢弃,它的位图/缓冲区可能会被重新循环,谁知道呢。

因此,在此方法之外使用 Canvas 是不安全的。画出你想要的,但仅限于内部onDraw()方法。

如果您想触发 View 重新绘制,请在其他时间调用invalidate().

例子:

渲染任何形状的视图类:

public class ShapeView extends View {

    private Paint mPaint;
    private ShapeRenderer mRenderer;

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

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

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

    private void init(){
        mPaint = new Paint();
    }

    public void setPaintColor(int color){
        mPaint.setColor(color);
    }

    public void setPaintStrokeWidth(float width){
        mPaint.setStrokeWidth(width);
    }

    public void setRenderer(ShapeRenderer renderer) {
        mRenderer = renderer;
    }

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

        if(mRenderer != null){
            mRenderer.drawShape(canvas,mPaint);
        }
    }

    public static interface ShapeRenderer{
        public void drawShape(Canvas canvas, Paint paint);
    }
}

一个绘制矩形的类:

public class RectRenderer implements ShapeView.ShapeRenderer {
    @Override
    public void drawShape(Canvas canvas, Paint paint) {
        canvas.drawRect(0,0,100,100,paint);
    }
}

在运行时绘制形状:

 myShapeView.setPaintColor(Color.GREEN);
 myShapeView.setPaintStroke(5f);
 myShapeView.setRenderer(new RectRenderer());
 myShapeView.invalidate();
于 2013-07-11T14:52:45.377 回答
1

我用以下更改了您的代码。

public class ShapesView extends View {

    Paint mypaint;

    public ShapesView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mypaint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mypaint.setColor(Color.BLUE);
        canvas.drawRect(30, 30, 200, 200, mypaint);
    }
}

当你想画画时,打电话shapesview.invalidate();

于 2013-07-11T14:34:39.617 回答
0

我认为您必须重新设计您的组件,以便它可以在 onDraw 方法中绘制自己。如果你需要一些必须包含 Canvas 的类,你可以尝试做这样的事情。

class Drawer {
  private Canvas canvas;

  public Drawer(Canvas canvas) {
    this.canvas = canvas;
  }

  public void DrawRectangle() {
    Paint mypaint = new Paint();
    mypaint.setColor(Color.BLUE);
    canvas.drawRect(30, 30, 200, 200, mypaint);
  }
}

在您的自定义视图上,您​​可以执行类似的操作。

public class ShapesView extends View{

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

  @Override
  protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    Drawer drawer = new Drawer(canvas);
    drawer.DrawRectangle();
  }

  public void DrawRectangle() {
    Paint mypaint = new Paint();
    mypaint.setColor(Color.BLUE);
    canvas.drawRect(30, 30, 200, 200, mypaint);
  }
}
于 2013-07-11T14:41:59.967 回答