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);
}
}
- 如果您的目标是在 SurfaceView 的表面(而不是 SurfaceView 的视图)上绘制,请不要覆盖
onDraw()
。 onDraw()
用于 custom views。如果您真的想使用 Surface,请将该方法命名为其他名称。
- 不要只在
surfaceChanged()
中绘图,除非您发布的是静态图片。该方法通常会在首次创建 Surface 时被调用一次,除非有什么改变了 Surface 的大小。如果您只想要位图中的静态图像,请考虑改用 ImageView。
- 不要假设
lockCanvas()
会成功。从 surfaceChanged()
调用它是非常安全的,但通常您需要检查 return 值。
- 不要假设
BitmapFactory.decodeResource()
会成功。
由于您的 drawColor()
调用成功,而您的 drawBitmap()
调用失败,我猜测 mBMPField
为空。根据 decodeResource()
:
的文档
[Returns] The decoded bitmap, or null if the image data could not be decoded, ...
出错时 return 为 null,而不是抛出异常,因此您需要检查 return 值。
好的,我的构造函数中没有声明初始化函数。所以一旦我开始使用 Init();我让它工作了。再次感谢您的指点和指导。没有它我不会注意到这部分。
因此,我在 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);
}
}
- 如果您的目标是在 SurfaceView 的表面(而不是 SurfaceView 的视图)上绘制,请不要覆盖
onDraw()
。onDraw()
用于 custom views。如果您真的想使用 Surface,请将该方法命名为其他名称。 - 不要只在
surfaceChanged()
中绘图,除非您发布的是静态图片。该方法通常会在首次创建 Surface 时被调用一次,除非有什么改变了 Surface 的大小。如果您只想要位图中的静态图像,请考虑改用 ImageView。 - 不要假设
lockCanvas()
会成功。从surfaceChanged()
调用它是非常安全的,但通常您需要检查 return 值。 - 不要假设
BitmapFactory.decodeResource()
会成功。
由于您的 drawColor()
调用成功,而您的 drawBitmap()
调用失败,我猜测 mBMPField
为空。根据 decodeResource()
:
[Returns] The decoded bitmap, or null if the image data could not be decoded, ...
出错时 return 为 null,而不是抛出异常,因此您需要检查 return 值。
好的,我的构造函数中没有声明初始化函数。所以一旦我开始使用 Init();我让它工作了。再次感谢您的指点和指导。没有它我不会注意到这部分。