Android 自定义 SurfaceView Class

Android SurfaceView in Custom Class

因此,我在 Android Studio 中进行的项目中将 运行 保留在 NullPointerException 中。我需要让图像显示在自定义 class 中,我正在调用 DrawSurface。我似乎找不到与我的问题相关的任何内容。我查了很多以前的问题,看了很多视频。

我抛出的错误如下所示:

java.lang.NullPointerException   at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1269)   at android.graphics.Canvas.drawBitmap(Canvas.java:1325)   at edu.########.#####.cse.treasurehunter.###########.DrawSurface.onDraw_Original(DrawSurface.java:60)   at edu.########.#####.cse.treasurehunter.###########.DrawSurface.onDraw(DrawSurface.java:-1)

我的 .xml 看起来像这样:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="fill_parent" android:orientation="vertical" tools:context=".MainActivity">
<edu.########.####.cse.treasurehunter.###########.DrawSurface android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:id="@+id/dsField"/>
<LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="50dp">
    <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.5" android:text="View Inventory" android:id="@+id/btnInventory"/>
    <Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.5" android:text="Credits" android:id="@+id/btnCredits"/>
</LinearLayout>

我的 DrawSurface class 看起来像这样:

public class DrawSurface extends SurfaceView {
private Bitmap mBMPField;
private SurfaceHolder holder;

public DrawSurface(Context context) {
    super(context);
    holder = getHolder();
    holder.addCallback(new SurfaceHolder.Callback() {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {

        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Canvas c = holder.lockCanvas();
            onDraw(c);
            holder.unlockCanvasAndPost(c);
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
    });
    mBMPField = BitmapFactory.decodeResource(getResources(), R.drawable.field);
}

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

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

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.DKGRAY);
    canvas.drawBitmap(mBMPField, 100, 200, null);
}

}

  1. 如果您的目标是在 SurfaceView 的表面(而不是 SurfaceView 的视图)上绘制,请不要覆盖 onDraw()onDraw() 用于 custom views。如果您真的想使用 Surface,请将该方法命名为其他名称。
  2. 不要只在 surfaceChanged() 中绘图,除非您发布的是静态图片。该方法通常会在首次创建 Surface 时被调用一次,除非有什么改变了 Surface 的大小。如果您只想要位图中的静态图像,请考虑改用 ImageView。
  3. 不要假设 lockCanvas() 会成功。从 surfaceChanged() 调用它是非常安全的,但通常您需要检查 return 值。
  4. 不要假设 BitmapFactory.decodeResource() 会成功。

由于您的 drawColor() 调用成功,而您的 drawBitmap() 调用失败,我猜测 mBMPField 为空。根据 decodeResource():

的文档

[Returns] The decoded bitmap, or null if the image data could not be decoded, ...

出错时 return 为 null,而不是抛出异常,因此您需要检查 return 值。

好的,我的构造函数中没有声明初始化函数。所以一旦我开始使用 Init();我让它工作了。再次感谢您的指点和指导。没有它我不会注意到这部分。