无法使用自定义视图在 canvas 上绘图

Cannot draw on canvas with custom view

我有一个classGameActivity如下(我只是post相关部分):

public class GameActivity extends AppCompatActivity {

// initiate variables
private GameView mGameView;
private Display mDisplay;
private Point mSize;

public static int window_width = 0;
public static int window_height = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    mDisplay = getWindowManager().getDefaultDisplay();
    mSize = new Point();
    mDisplay.getSize(mSize);
    window_width = mSize.x;
    window_height = mSize.y;

    // initialize game view object
    mGameView = new GameView(this);

    // adding it to the content view
    //setContentView(mGameView);
    setContentView(R.layout.activity_game);
}

由于自定义视图,我有如下两个构造函数的 class GameView(也只是相关部分以保持清晰):

private Context mContext;

//These objects will be used for drawing
private SurfaceHolder mSurfaceHolder;
private Paint mPaint;

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

    Log.d("TEST","Constructor 1");

    init(context, null);

    // clear all lists
    ...

    // create object of map in beginning of game
    ...

    // create objects of HQs
    ...

   // create other sprite objects and add them to lists
   ...
}

public GameView(Context context, AttributeSet attrs) {
    super(context, attrs);

    Log.d("TEST","Constructor 2");

    init(context, attrs);

}

我在两个构造函数中都调用了 init() 方法

private void init(Context context, AttributeSet attrs) {
    mContext = context;
    mSurfaceHolder = getHolder();
    mPaint = new Paint();
    mPaint.setColor(Color.DKGRAY);
}

我的run()是这样的:

@Override
public void run(){


    Log.d("TEST","RUN");
    long current_time = 0;
    long old_time;


    while (playing) {
        old_time = current_time;


        // update the game
        update();

        //to draw the frame
        //onDraw(canvas);
        draw();

        //to control (lets the game sleep for some milliseconds)
        control();

        current_time = SystemClock.elapsedRealtime();

        frametime = current_time - old_time;
        framerate = 1000/ (current_time - old_time);

    }
}

draw()(错误发生的地方)是这样的:

private void draw() {
    // BUG: mSurfaceHolder.getSurface.isValid ist niemals valid

    Canvas canvas;

    //if(true){
    //checking if surface is valid
    if (mSurfaceHolder.getSurface().isValid()) {
        Log.d("Test","DRAW");

        //locking the canvas
        canvas = mSurfaceHolder.lockCanvas();

        //drawing a background color for canvas
        canvas.drawColor(Color.GREEN);

        // call draw methods here
        // bigger objects should be called before smaller objects for visibility
        draw_ground(canvas);
        draw_hq(canvas);
        draw_soldiers(canvas);
        draw_bullets(canvas);
        draw_HUD(canvas);

        //Unlocking the canvas
        mSurfaceHolder.unlockCanvasAndPost(canvas);
    }
}

不,问题是: 如果我在第一个 class GameActivity 中将 class GameView 的对象 mGameView 传递给 setContentView 一切都很好并且 draw() 方法工作正常,这意味着 mSurfaceHolder.getSurface().isValid()) 有效。

但是如果我输入第一个 class setContentView(R.layout.activity_game); 那么 mSurfaceHolder.getSurface().isValid()) 永远无效。其他一切正常(例如,我听到游戏声音)但他不画画。如果我不检查 mSurfaceHolder.getSurface().isValid()) 那么游戏就会崩溃,因为在下面的代码中 draw() canvas 是空的。

我的目标是创建自定义视图并用按钮覆盖它。

这里是 XML:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".GameActivity">



<!--Test-->

<com.example.mirco.battlefront.GameView
    android:id="@+id/gameView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<Button
    android:id="@+id/button"
    android:layout_width="119dp"
    android:layout_height="wrap_content"
    android:text="Button" />


<!--Test-->
</FrameLayout>

XML 似乎是正确的,因为 Android Studio 可以识别它(带有叠加按钮的自定义视图)。但他没有画进去。

就像我在 setContentView(mGameView); 中所说的那样,一切都很好,除了我只有一个视图,我无法在其中覆盖按钮等等,这不是我想要的。

我做错了什么?我试图尽可能地遵循 LINK。我已经尝试了几天来解决这个问题,但也找不到解决方案。

而不是

mGameView = new GameView(this);

    // adding it to the content view
    //setContentView(mGameView);
    setContentView(R.layout.activity_game);

你应该做

setContentView(R.layout.activity_game);
mGameView = (GameView)findViewById (R.id.gameView);

然后 mGameview 就是您布局中的那个。