【问题标题】:NullPointerException when creating a custom View with onDraw()使用 onDraw() 创建自定义视图时出现 NullPointerException
【发布时间】:2013-09-11 15:07:01
【问题描述】:

我正在创建一个添加到 FrameLayout 的自定义视图。 当我初始化视图时,我得到一个 NullPointerException。 我究竟做错了什么。视图的代码是:

public class DocumentCameraMask extends View {

    private Context mContext;

    public DocumentCameraMask(Context context) {
        super(context);

        this.mContext = context;
    }

    @Override
    public void draw(Canvas canvas) {
        // TODO Auto-generated method stub

        Paint paint = new Paint();
        paint.setColor(this.mContext.getResources().getColor(R.color.textColor));
        paint.setStyle(Paint.Style.STROKE);

        Rect cropRect = new Rect(0,0,800,600);
        canvas.drawRect(cropRect, paint);

        super.draw(canvas);

    }

}

cropRect 大小将动态计算,这就是我需要制作此视图的原因。 感谢您的帮助。

LogCat

09-11 19:13:04.590:E/AndroidRuntime(4235):致命异常:主要 09-11 19:13:04.590: E/AndroidRuntime(4235): java.lang.RuntimeException:无法启动活动 DocumentCameraActivity}: java.lang.NullPointerException 09-11 19:13:04.590: E/AndroidRuntime(4235):在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) 09-11 19:13:04.590: E/AndroidRuntime(4235): 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211) 09-11 19:13:04.590: E/AndroidRuntime(4235): 在 android.app.ActivityThread.access$600(ActivityThread.java:149) 09-11 19:13:04.590:E/AndroidRuntime(4235):在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1300) 09-11 19:13:04.590: E/AndroidRuntime(4235): 在 android.os.Handler.dispatchMessage(Handler.java:99) 09-11 19:13:04.590:E/AndroidRuntime(4235):在 android.os.Looper.loop(Looper.java:153) 09-11 19:13:04.590: E/AndroidRuntime(4235):在 android.app.ActivityThread.main(ActivityThread.java:4987) 09-11 19:13:04.590:E/AndroidRuntime(4235):在 java.lang.reflect.Method.invokeNative(Native Method) 09-11 19:13:04.590:E/AndroidRuntime(4235):在 java.lang.reflect.Method.invoke(Method.java:511) 09-11 19:13:04.590: E/AndroidRuntime(4235):在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821) 09-11 19:13:04.590: E/AndroidRuntime(4235): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584) 09-11 19:13:04.590:E/AndroidRuntime(4235):在 dalvik.system.NativeStart.main(本机方法)09-11 19:13:04.590: E/AndroidRuntime(4235):引起:java.lang.NullPointerException 09-11 19:13:04.590: E/AndroidRuntime(4235): 在 android.view.ViewConfiguration.get(ViewConfiguration.java:332) 09-11 19:13:04.590:E/AndroidRuntime(4235):在 android.view.View.(View.java:3243)

【问题讨论】:

  • 请发布您在问题中得到的错误堆栈跟踪(参见 logcat)。
  • 你可以在这里发布 logcat 吗?

标签: android view nullpointerexception


【解决方案1】:

您不必重写 Viewdraw() 方法,无论您想做什么绘图,都可以使用 onDraw() 方法。

public class DocumentCameraMask extends View {

        private Context mContext;

        public DocumentCameraMask(Context context) {
            super(context);

            this.mContext = context;
        }

        @Override
        public void onDraw(Canvas canvas) {
            // TODO Auto-generated method stub
            super.onDraw(canvas);
            Paint paint = new Paint();
            paint.setColor(this.mContext.getResources().getColor(R.color.textColor));
            paint.setStyle(Paint.Style.STROKE);

            Rect cropRect = new Rect(0,0,800,600);
            canvas.drawRect(cropRect, paint);             

        }

    }

参考:

1. google link

2.另一个link这可能对你有帮助

更新:

我的主要活动:

public class MainActivity extends Activity {
DocumentCameraMask mask;
    RelativeLayout rel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rel = (RelativeLayout) findViewById(R.id.t);
mask = new DocumentCameraMask(this);

        mask.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));
        byte b = 100;
        int a = b;
        Toast.makeText(this,"Int "+a,Toast.LENGTH_LONG).show();

rel.addView(mask);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

自定义视图 DocumentCameraMask 类:

public class DocumentCameraMask extends View {

        private Context mContext;

        public DocumentCameraMask(Context context) {
            super(context);

            this.mContext = context;
        }

        @Override
        public void onDraw(Canvas canvas) {
            // TODO Auto-generated method stub
            super.onDraw(canvas);
            Paint paint = new Paint();
            paint.setColor(Color.BLUE);
            paint.setStyle(Paint.Style.STROKE);

            Rect cropRect = new Rect(0,0,800,600);
            canvas.drawRect(cropRect, paint);             

        }

    }

输出:

【讨论】:

  • 这没什么区别,因为 onDraw 调用 draw();
  • 但在 google android doc 中建议使用,您不必更改 draw() 方法。
  • Google android 文档非常过时且无用。如果它有用,我就不会花 3 个小时来尝试解决如此直接的问题。原谅通风;在 Eclipse 中,如果您尝试调用 onDraw(),它会要求您覆盖我所做的 draw()。
  • 正如 Gru 所说,你真的不必重写 draw(),重写 onDraw() 会为你完成这项工作。 Refer this
  • @W.K.S 检查我更新的答案,您的 Eclipse 可能有问题。View 既不是 Abstract class 也不是 Interface 那么 eclipse 如何建议您使用 override 方法?
【解决方案2】:

您需要添加另一个构造函数。特别是,如果您在 XML 文件中使用此 View,它会使用您未提供的不同构造函数。

View 的三个构造函数是:

View(Context context, AttributeSet attrs, int defStyle)

View(Context context, AttributeSet attrs)

View(Context context)

至少,您应该覆盖第二个,因为这是从 XML 文件中最常调用的内容。只需确保为每个人拨打匹配的super()


注意:

正如 Gru 所说,您确实应该覆盖 onDraw(),而不是 draw()。我不知道你的 Eclipse 告诉你什么,但我从来不需要覆盖 draw(),也从来没有建议我这样做。

【讨论】:

    【解决方案3】:

    您可以尝试以下操作:

    public class DocumentCameraMask extends View {
    
        private Context mContext;
    
        /*
        If you ever want to include custom-view manually in code without any layout      attributes,use this constructor.
        */ 
    
        public DocumentCameraMask(Context context) {
            this(context,null);       
        }
    
        /*
          If you want to include the custom view in a layout XML file, you need to use this 
          constructor. 
        */ 
        public DocumentCameraMask(Context context,AttributeSet attrs) {
            super(context,attrs);
            this.mContext = context;        
        }    
    
    
        /*
         If you need to actually do something with the view you have. To do this, you must   override the onDraw method of your custom-View class.
         */
    
        @Override
        public void onDraw(Canvas canvas) {
    
            /*
              If you want to call the superclass onDraw method (eg.TextView rather than a generic View), then call super.onDraw().If you don't want that, i.e. you are planning to draw the entire View yourself ,there's no reason to call it. If you look at the source code, it shows that View.onDraw() is an empty method. So, calling super.onDraw(), if the parent class is View itself, does nothing. 
             */
    
            super.onDraw(canvas);
    
            Paint paint = new Paint();
            paint.setColor(mContext.getResources().getColor(R.color.textColor));
            paint.setStyle(Paint.Style.STROKE);
    
            Rect cropRect = new Rect(0,0,800,600);
            canvas.drawRect(cropRect, paint);
        }      
    }
    

    您可以参考Custom Drawing

    注意:根据文档,

    1. 公共 void 绘制(Canvas 画布)

    在 API 级别 1 中添加

    Manually render this view (and all of its children) to the given Canvas. 
    The view must have already done a full layout before this function is called. 
    When implementing a view, implement onDraw(android.graphics.Canvas) 
    instead of overriding this method. If you do need to override this method,
    call the superclass version.
    
      2. protected void onDraw (Canvas canvas)
    

    在 API 级别 1 中添加

    Implement this to do your drawing.
    

    【讨论】:

      猜你喜欢
      • 2017-05-17
      • 2013-02-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多