在Android上创建自定义视图时出现Nullpointer错误onDraw?

时间:2013-06-17 04:35:56

标签: android view

我正在做一个小型绘画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的新手,所以非常感谢你帮助我!

1 个答案:

答案 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();