Android测验游戏 - 每个qstion的倒数计时器 [英] Android Quiz Game - Countdown timer for each qstion

查看:122
本文介绍了Android测验游戏 - 每个qstion的倒数计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下教程为Android创建了一个Quiz应用程序: http://automateddeveloper.blogspot.co.uk/2011/06/getting-started-complete-android-app.html

I have created a Quiz app for Android using the tutorial here: http://automateddeveloper.blogspot.co.uk/2011/06/getting-started-complete-android-app.html

对于每个问题,用户只有20秒的时间来回答它。如果他/她在20秒内未能回答,将弹出 AlertDialog ,游戏将终止。

For each question, the user will only have 20 seconds to answer it. If he/she fails to answer in 20 seconds, an AlertDialog will popup and the game will terminate.

至这样做,我在 OnCreate 方法中添加了一个计数器 QuestionActivity类

To do this, I have added a counter in the OnCreate method of QuestionActivity class:

final TextView myCounter = (TextView) findViewById(R.id.countdown);
    new CountDownTimer(20000, 1000) {

        @Override
        public void onFinish() {
            timeUp();
        }

        @Override
        public void onTick(long millisUntilFinished) {
            myCounter.setText("Time left: "
                    + String.valueOf(millisUntilFinished / 1000));
        }

    }.start();


public void timeUp() {

    AlertDialog.Builder builder = new AlertDialog.Builder(
            QuestionActivity.this);
    builder.setTitle("Times up!")
            .setMessage("Game over")
            .setCancelable(false)
            .setNeutralButton(android.R.string.ok,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            QuestionActivity.this.finish();
                        }
                    });
    AlertDialog alert = builder.create();
    alert.show();
}

计数器在屏幕上正常显示和运行功能。回答问题后,活动转到下一个问题,计数器再次重置为20秒。

The counter works displays and functions on screen correctly. After answering a question, the activity moves to the next question and the counter resets itself to 20 seconds again.

问题

测验有15个问题,在回答3或4个问题后,应用程序崩溃,我收到以下错误:

The quiz has 15 questions, after answering 3 or 4 questions, the app crashes and I get the following error:

07-18 00:49:05.530: E/AndroidRuntime(4867): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@41533a80 is not valid; is your activity running?

我认为这与 AlertDialog 有关。我在Stackoverflow上查找了这个错误代码,流行的解决方案是在构建 AlertDialog ActivityName.this 作为上下文传递C>。

I believe this relates to the AlertDialog. I have looked up this error code on Stackoverflow and the popular solution is to pass ActivityName.this as the context when building the AlertDialog.

不幸的是,这并没有解决问题。

Unfortunately this does not solve the problem.

我相信计数器设定的时间限制为20秒整个活动。我的要求是每个问题20秒。

I believe the counter is setting a time limit of 20 seconds for the whole activity. My requirement is 20 seconds for each question.

然而,当用户按下下一步按钮时,计数器将重置为20秒,并且活动将移至下一个问题。

However, the counter resets to 20 seconds when the user press the' Next button and the activity moves to the next question.

当用户按下下一步按钮时,我应该重置计数器吗?这是 OnClickListener 代码下一步按钮

Should I be resetting the counter when the user presses the Next button? Here is the OnClickListener code for the Next button

if (currentGame.isGameOver()) {
        Intent i = new Intent(this, EndgameActivity.class);
        startActivity(i);
        finish();
    } else {
        Intent i = new Intent(this, QuestionActivity.class);
        startActivity(i);
                    SHOULD I ADD SOMETHING HERE?
        finish();

任何人都可以帮我编码解决问题的方法吗?

以下是 QuestionActivity.class中的所有代码

public class QuestionActivity extends SherlockActivity implements
    OnClickListener {

private Question currentQ;
private GamePlay currentGame;
private Context context;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.question);

    getSupportActionBar().hide();
    /**
     * Configure current game and get question
     */
    currentGame = ((ChuckApplication) getApplication()).getCurrentGame();
    currentQ = currentGame.getNextQuestion();

    Button nextBtn = (Button) findViewById(R.id.nextBtn);
    nextBtn.setOnClickListener(this);

    Button quitBtn = (Button) findViewById(R.id.quitBtn);
    quitBtn.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            finish();
        }
    });

    //Update the question and answer options..
    setQuestions();

    final TextView myCounter = (TextView) findViewById(R.id.countdown);
    new CountDownTimer(20000, 1000) {

        @Override
        public void onFinish() {
            // myCounter.setText("Time up!");
            timeUp(context);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            myCounter.setText("Time left: "
                    + String.valueOf(millisUntilFinished / 1000));
        }
    }.start();
}

public void timeUp(Context context) {

    AlertDialog.Builder builder = new AlertDialog.Builder(
            QuestionActivity.this);
    builder.setTitle("Times up!")
            .setMessage("Game over")
            .setCancelable(false)
            .setNeutralButton(android.R.string.ok,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            QuestionActivity.this.finish();
                        }
                    });
    AlertDialog alert = builder.create();
    alert.show();
}

/**
 * Method to set the text for the question and answers from the current
 * games current question
 */
private void setQuestions() {
    // set the question text from current question
    String question = Utility.capitalise(currentQ.getQuestion()) + "?";
    TextView qText = (TextView) findViewById(R.id.question);
    qText.setText(question);

    // set the available options
    List<String> answers = currentQ.getQuestionOptions();
    TextView option1 = (TextView) findViewById(R.id.answer1);
    option1.setText(Utility.capitalise(answers.get(0)));

    TextView option2 = (TextView) findViewById(R.id.answer2);
    option2.setText(Utility.capitalise(answers.get(1)));

    TextView option3 = (TextView) findViewById(R.id.answer3);
    option3.setText(Utility.capitalise(answers.get(2)));

    TextView option4 = (TextView) findViewById(R.id.answer4);
    option4.setText(Utility.capitalise(answers.get(3)));
}

public void onClick(View arg0) {
    //validate a checkbox has been selected
    if (!checkAnswer())
        return;

    //check if end of game
    if (currentGame.isGameOver()) {
        Intent i = new Intent(this, EndgameActivity.class);
        startActivity(i);
        finish();
    } else {
        Intent i = new Intent(this, QuestionActivity.class);
        startActivity(i);
        finish();
    }
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
    case KeyEvent.KEYCODE_BACK:
        return true;
    }

    return super.onKeyDown(keyCode, event);
}

/**
 * Check if a checkbox has been selected, and if it has then check if its
 * correct and update gamescore
 */
private boolean checkAnswer() {
    String answer = getSelectedAnswer();
    if (answer == null) {
        // Log.d("Questions", "No Checkbox selection made - returning");
        return false;
    } else {
        // Log.d("Questions",
        // "Valid Checkbox selection made - check if correct");
        if (currentQ.getAnswer().equalsIgnoreCase(answer)) {
            // Log.d("Questions", "Correct Answer!");
            currentGame.incrementRightAnswers();
        } else {
            // Log.d("Questions", "Incorrect Answer!");
            currentGame.incrementWrongAnswers();
        }
        return true;
    }
}

private String getSelectedAnswer() {
    RadioButton c1 = (RadioButton) findViewById(R.id.answer1);
    RadioButton c2 = (RadioButton) findViewById(R.id.answer2);
    RadioButton c3 = (RadioButton) findViewById(R.id.answer3);
    RadioButton c4 = (RadioButton) findViewById(R.id.answer4);
    if (c1.isChecked()) {
        return c1.getText().toString();
    }
    if (c2.isChecked()) {
        return c2.getText().toString();
    }
    if (c3.isChecked()) {
        return c3.getText().toString();
    }
    if (c4.isChecked()) {
        return c4.getText().toString();
    }

    return null;
}


推荐答案

我认为活动没有当你尝试进行对话时,某个点上可能存在(可能是 CountDownTimer 接近结束时?!?)。

I think the activity doesn't exist anymore at a certain point when you try to make the dialog(probably when the CountDownTimer is near the end?!?).

无论如何,我认为为每个问题完成并启动相同的活动并不是一个好主意,而是可以使用当前活动并只需重新启动计时器。例如:

Anyway I think finishing and starting the same activity for each question isn't such a good idea, instead you could use the current activity and simply restart the timer. For example:

public class QuestionActivity extends SherlockActivity implements
    OnClickListener {

   private CountDownTimer mCountDown;

   @Override
   public void onCreate(Bundle savedInstanceState) {
      // ...
      mCountDown = new CountDownTimer(20000, 1000) {

        @Override
        public void onFinish() {
            // myCounter.setText("Time up!");
            timeUp(context);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            myCounter.setText("Time left: "
                    + String.valueOf(millisUntilFinished / 1000));
        }
      }.start();
      // ... 

onClick 回调做同样的事情来设置一个新问题,停止旧计时器并重启新计时器:

and in the onClick callback do the same to setup a new question, stop the old timer and restart the new timer:

//check if end of game
if (currentGame.isGameOver()) {
    Intent i = new Intent(this, EndgameActivity.class);
    startActivity(i);
    finish();
} else {
    if (mCountDown != null) { 
       mCountDown.cancel();
    }  
    currentQ = currentGame.getNextQuestion();
    setQuestions();
    mCountDown = new CountDownTimer(20000, 1000) {

        @Override
        public void onFinish() {
            // myCounter.setText("Time up!");
            timeUp(context);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            myCounter.setText("Time left: "
                    + String.valueOf(millisUntilFinished / 1000));
        }
    }.start();  
}

此外,在对话框的回调中's 按钮在完成活动之前,我会先关闭对话框

Also, in the callback for the Dialog's Button I would first close the Dialog before finishing the Activity:

((AlertDialog) dialog).dismiss();
QuestionActivity.this.finish();

这篇关于Android测验游戏 - 每个qstion的倒数计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆