我正在做一个小型绘画android应用程序。我想创建一个自定义视图来绘制一些东西。当创建布局并添加我的视图时。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.androidpaint.PaintView
android:id="@+id/paintPlace"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</RelativeLayout>
错误
java.lang.NullPointerException
Exception details are logged in Window > Show View > Error Log
java.lang.NullPointerException
at android.graphics.Canvas.drawPath(Canvas.java:1021)
at com.example.androidpaint.PaintView.onDraw(PaintView.java:69)
at android.view.View.draw(View.java:13712)
at android.view.View.draw(View.java:13596)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13594)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13594)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13715)
at android.view.View.draw(View.java:13596)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13715)
这是我的PaintView类:
public class PaintView extends View{
boolean isEraser = false;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private Paint mPaint;
private Paint mPaintScreen;
int color;
public PaintView(Context c) {
super(c);
mPaintScreen = new Paint();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);
color = mPaint.getColor();
mPath = new Path();
mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PaintView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmap.eraseColor(Color.WHITE);
}
private float mX =-100, mY = -100;
Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.background );
private static final float TOUCH_TOLERANCE = 7;
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap,0,0,mPaintScreen);
canvas.drawPath(mPath, mPaint);
canvas.drawBitmap(b, 10, 10, mPaint);
}
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x -mX);
float dy = Math.abs(y - mY);
if(dx>=TOUCH_TOLERANCE||dy>=TOUCH_TOLERANCE){
mPath.quadTo(mX,mY, (x+mX)/2, (y+mY)/2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
mX =-100;
mY = -100;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
break;
case MotionEvent.ACTION_UP:
touch_up();
break;
}
postInvalidate();
return true;
}
public void setColor(int c){
if(isEraser)
mPaint.setColor(Color.WHITE);
else{
mPaint.setColor(Color.CYAN);
//mPaint.setColor(c);
color = c;
postInvalidate();
}
}
public float getLineWidth(){
return mPaint.getStrokeWidth();
}
public void setLineWidth(float w){
mPaint.setStrokeWidth(w);
}
public int getDrawingColor(){
return mPaint.getColor();
}
public void clearPaint(){
mPath.reset();
mBitmap.eraseColor(Color.WHITE);
invalidate();
}
public void setEraserIcon(){
b = BitmapFactory.decodeResource(getResources(),R.drawable.eraser );
color = mPaint.getColor();
mPaint.setColor(Color.WHITE);
isEraser = true;
}
public void setBrushIcon(){
b = BitmapFactory.decodeResource(getResources(),R.drawable.brush );
mPaint.setColor(color);
isEraser = false;
}
public void saveImage(){
String fileName = "Image" + System.currentTimeMillis();
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE,fileName);
values.put(Images.Media.DATE_ADDED,System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE,"image/jpeg");
Uri uri = getContext().getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
try{
OutputStream outStream = getContext().getContentResolver().openOutputStream(uri);
mBitmap.compress(Bitmap.CompressFormat.JPEG,100, outStream);
outStream.flush();
outStream.close();
Toast message = Toast.makeText(getContext(), R.string.message_saved, Toast.LENGTH_SHORT);
message.setGravity(Gravity.CENTER, message.getXOffset(),message.getYOffset());
message.show();
}catch(Exception ex){
Toast message = Toast.makeText(getContext(),R.string.message_error_saving, Toast.LENGTH_SHORT);
message.setGravity(Gravity.CENTER, message.getXOffset()/2,message.getYOffset()/2);
message.show();
}
}
}`
我创建了一个新的Activity并设置了这样的代码:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(new PaintView(this));
}
但是当我调用包含PaintView的XML时。我上面说的错误
我是android的新手,所以非常感谢你帮助我!
答案 0 :(得分:3)
尝试在public PaintView(Context context, AttributeSet attrs)
构造函数中添加初始化代码。所以它看起来像:
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintScreen = new Paint();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);
color = mPaint.getColor();
mPath = new Path();
mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
并且不是setContentView(new PaintView(this));
,而是setContentView(your.xml);
,您的视图作为标记。
您得到NullPointerException
因为您未正确初始化自定义View
。
在XML文件中创建View
时,将调用YourView(Context context, AttributeSet attrs)
构造函数。
使用YourView view = new YourView(this)' - 'YourView(Context context)
动态创建视图时调用。
为了防止这种情况,你可以在里面初始化初始化你的组件创建一个小方法,然后从每个构造函数调用这个方法。
如果要为绘图动态设置其他值,则需要在每次更改后调用invalidate();
。