2012-07-18 40 views
2

我在这里使用教程创建的Android测验的应用程序倒数计时器:http://automateddeveloper.blogspot.co.uk/2011/06/getting-started-complete-android-app.htmlAndroid的问答游戏 - 每个qstion

对于每一个问题,用户将只需要20秒的回答。如果他/她在20秒内未能回答,将弹出一个AlertDialog并且游戏将终止。

要做到这一点,我已经在QuestionActivity classOnCreate方法添加计数器:

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秒。

问题

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

07-18 00:49:05.530: E/AndroidRuntime(4867): android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running? 

我认为这涉及到AlertDialog。我在Stackoverflow上查找了这个错误代码,当构建AlertDialog时,流行的解决方案是通过ActivityName.this作为上下文。

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

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

但是,当用户按下'Next'按钮并且活动移动到下一个问题时,计数器重置为20秒。

我应该在用户按下Next按钮时重置计数器吗?下面是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(); 

谁能帮我编写一个解决我的问题OnClickListener代码?

这里是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; 
} 

回答

6

所有的代码,我觉得活动不再在某一点,当你试图让对话框(可能当CountDownTimer已经接近尾声存在? ?)。

无论如何,我认为每个问题的整理和开始相同的活动并不是一个好主意,而是可以使用当前活动并简单地重新启动计时器。例如:

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回调做同样配置了新的问题,停止旧计时器并重新启动新的计时器:

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

而且,在回调为Dialog“小号Button我首先将完成Activity之前关闭Dialog

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

感谢花花公子。今晚我回到家时,我会试试这个。 – tiptopjat 2012-07-18 09:55:08

+0

我已经添加了所有代码,并且计数器问题已得到修复。然而,当测验结束,我开始EndgameActivity.class,20秒后,我得到一个WindowManager的$ BadTokenException错误。它看起来像计时器仍在运行,并试图显示AlertDialog。我在开始EndgameActivity活动后使用finish()。任何想法我做错了什么? – tiptopjat 2012-07-18 20:00:23

+1

@tiptopjat添加相同的代码来停止游戏结束时的计时器:'if(currentGame.isGameOver()){if(mCountDown!= null){mCountDown.cancel(); } ...'看看它是否解决了这个问题。 – Luksprog 2012-07-18 20:02:41