2012-07-18 95 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