java Android 问答游戏 - 每个问题的倒数计时器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11532684/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android Quiz Game - Countdown timer for each qstion
提问by tiptopjat
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
我使用这里的教程为 Android 创建了一个测验应用程序:http: //automateddeveloper.blogspot.co.uk/2011/06/getting-started-complete-android-app.html
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.
对于每个问题,用户只有 20 秒的时间来回答。如果他/她在 20 秒内没有回答,AlertDialog
会弹出一个遗嘱,游戏将终止。
To do this, I have added a counter in the OnCreate
method of QuestionActivity class
:
为此,我在OnCreate
方法中添加了一个计数器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();
}
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.
计数器在屏幕上正常显示和运行。回答一个问题后,活动移至下一个问题,计数器再次重置为 20 秒。
The problem
问题
The quiz has 15 questions, after answering 3 or 4 questions, the app crashes and I get the following error:
测验有 15 个问题,回答 3 或 4 个问题后,应用程序崩溃并出现以下错误:
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?
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
.
我相信这与AlertDialog
. 我在 Stackoverflow 上查找过这个错误代码,流行的解决方案是ActivityName.this
在构建AlertDialog
.
Unfortunately this does not solve the problem.
不幸的是,这并不能解决问题。
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 秒的时间限制。我的要求是每个问题 20 秒。
However, the counter resets to 20 seconds when the user press the' Next
button and the activity moves to the next question.
但是,当用户按下 'Next
按钮并且活动移动到下一个问题时,计数器会重置为 20 秒。
Should I be resetting the counter when the user presses the Next
button? Here is the OnClickListener
code for the Next
button
当用户按下Next
按钮时,我应该重置计数器吗?这是按钮的OnClickListener
代码Next
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();
Can anyone help me code a solution to my problem?
谁能帮我编写代码来解决我的问题?
Here is all the code in QuestionActivity.class
这里是所有的代码 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;
}
回答by Luksprog
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?!?).
我认为当您尝试进行对话时(可能CountDownTimer
是在接近尾声时?!?),该活动在某个时刻不再存在。
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();
// ...
and in the onClick
callback do the same to setup a new question, stop the old timer and restart the new timer:
并在onClick
回调中执行相同操作以设置新问题,停止旧计时器并重新启动新计时器:
//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();
}
Also, in the callback for the Dialog
's Button
I would first close the Dialog
before finishing the Activity
:
另外,在Dialog
's的回调中,Button
我会Dialog
在完成之前先关闭Activity
:
((AlertDialog) dialog).dismiss();
QuestionActivity.this.finish();