无法从Android中的其他类调用自定义绘制方法

时间:2013-07-11 14:26:20

标签: android android-custom-view

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

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

ShapesView

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 个答案:

答案 0 :(得分:2)

如果我理解你的问题,你需要一个自定义视图(一个按钮),它将根据某些事件以不同的方式绘制自己。如果是这种情况,那么您需要尊重Android关于视图绘制的指南,看看here

现在,您的案例的一个可能的解决方案是设置关于视图状态的某种标志,然后在准备好绘制时使用该标志。例如,您可以这样做:

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

然后,只要您需要从活动中绘制视图,就可以使用以下内容:

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

在您的代码中,您正在执行的是在活动的onCreate期间调用视图函数,而onCreate会依次尝试使用空画布,因为在此期间未调用视图的onDraw方法。此外,正如其他人指出的那样,你不能在onDraw方法之外使用画布对象。

希望这会有所帮助......

答案 1 :(得分: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();

答案 2 :(得分:1)

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

完成onDraw()后,可以处理canvas,其位图/缓冲区可以重新循环,谁知道。

因此,在此方法之外使用Canvas是不安全的。画出你想要的东西,但只能在onDraw()方法中。

如果您想触发视图重新绘制,请在其他时间拨打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();

答案 3 :(得分: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);
  }
}