首页 > 解决方案 > 无法使用自定义视图在画布上绘图

问题描述

我有一个课程GameActivity如下(我只是发布相关部分):

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);
}

由于自定义视图(也只是相关部分保持清晰) ,我有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);
    }
}

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

但是,如果我上第一堂课,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);一切都很好,只是我只有一个视图不能覆盖按钮等等,这不是我想要的。

我究竟做错了什么?我试图尽可能好地遵循该链接。我正在尝试几天来解决这个问题,但也无法在任何地方找到解决方案。

标签: javaandroidandroid-custom-viewsurfaceview

解决方案


代替

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 是您布局中的一个。


推荐阅读