Android Studio CountDownTimer 不工作
Android Studio CountDownTimer not working
我目前正在开发一个简单的测验应用程序,我尝试使用一个计时器,它只允许您在 10 秒内回答问题,然后再转到下一个问题。
虽然,计时器没有按我想要的方式工作。大约 5 秒后问题发生变化,但应用程序甚至没有显示它,它一直停留在 10,如下所示:
这是 QuestionActivity class:
的代码
package com.example.myquiz;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.Animator;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
@RequiresApi(api = Build.VERSION_CODES.O)
public class QuestionActivity extends AppCompatActivity implements View.OnClickListener {
private TextView question, qCount, timer;
private Button option1, option2, option3, option4;
private List<Question> questionList;
private int quesNum;
private CountDownTimer countDown;
private int score;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question);
question = findViewById(R.id.question);
qCount = findViewById(R.id.quest_num);
timer = findViewById(R.id.countdown);
option1 = findViewById(R.id.option1);
option2 = findViewById(R.id.option2);
option3 = findViewById(R.id.option3);
option4 = findViewById(R.id.option4);
option1.setOnClickListener(this);
option2.setOnClickListener(this);
option3.setOnClickListener(this);
option4.setOnClickListener(this);
getQuestionsList();
score = 0;
}
private void getQuestionsList() {
questionList = new ArrayList<>();
questionList.add(new Question("Question1", "A", "B", "C", "D", 2));
questionList.add(new Question("Question2", "B", "B", "D", "A", 2));
questionList.add(new Question("Question3", "C", "B", "A", "D", 2));
questionList.add(new Question("Question4", "A", "D", "C", "B", 2));
questionList.add(new Question("Question5", "C", "D", "A", "D", 2));
setQuestion();
}
private void setQuestion() {
timer.setText(String.valueOf(10));
question.setText(questionList.get(0).getQuestion());
option1.setText(questionList.get(0).getOptionA());
option2.setText(questionList.get(0).getOptionB());
option3.setText(questionList.get(0).getOptionC());
option4.setText(questionList.get(0).getOptionD());
qCount.setText(String.valueOf(1) + "/" + String.valueOf(questionList.size()));
startTimer();
quesNum = 0;
}
private void startTimer() {
countDown = new CountDownTimer(12000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
if (millisUntilFinished < 10)
timer.setText(String.valueOf(millisUntilFinished/1000));
}
@Override
public void onFinish() {
changeQuestion();
}
};
countDown.start();
}
@Override
public void onClick(View v) {
int selectedOption = 0;
switch (v.getId()) {
case R.id.option1:
selectedOption = 1;
break;
case R.id.option2:
selectedOption = 2;
break;
case R.id.option3:
selectedOption = 3;
break;
case R.id.option4:
selectedOption = 4;
break;
default:
}
countDown.cancel();
checkAnswer(selectedOption, v);
}
private void checkAnswer(int selectedOption, View view) {
if (selectedOption == questionList.get(quesNum).getCorrectAns()) {
//Right Answer
((Button) view).setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
score++;
} else {
//Wrong Answer
((Button) view).setBackgroundTintList(ColorStateList.valueOf(Color.RED));
switch (questionList.get(quesNum).getCorrectAns()) {
case 1:
option1.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
case 2:
option2.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
case 3:
option3.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
case 4:
option4.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
}
}
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
changeQuestion();
}
}, 2000);
}
private void changeQuestion() {
if (quesNum < questionList.size() - 1) {
quesNum++;
playAnim(question, 0, 0);
playAnim(option1, 0, 1);
playAnim(option2, 0, 2);
playAnim(option3, 0, 3);
playAnim(option4, 0, 4);
qCount.setText(String.valueOf(quesNum + 1) + "/" + String.valueOf(questionList.size()));
timer.setText(String.valueOf(10));
startTimer();
} else {
//Go to Score Activity
Intent intent = new Intent(QuestionActivity.this, ScoreActivity.class);
intent.putExtra("SCORE",String.valueOf(score) + "/" + String.valueOf(questionList.size()));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
QuestionActivity.this.finish();
}
}
private void playAnim(View view, final int value, int viewNum) {
view.animate().alpha(value).scaleX(value).scaleY(value).setDuration(500).setStartDelay(100).setInterpolator(new DecelerateInterpolator()).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (value == 0) {
switch (viewNum) {
case 0:
((TextView) view).setText(questionList.get(quesNum).getQuestion());
break;
case 1:
((Button) view).setText(questionList.get(quesNum).getOptionA());
break;
case 2:
((Button) view).setText(questionList.get(quesNum).getOptionB());
break;
case 3:
((Button) view).setText(questionList.get(quesNum).getOptionC());
break;
case 4:
((Button) view).setText(questionList.get(quesNum).getOptionD());
break;
}
if (viewNum != 0)
((Button) view).setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#e8c1e1")));
playAnim(view, 1, viewNum);
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
countDown.cancel();
}
}
我该如何解决?
您的 onTick
有一个问题 - 我假设您希望它在倒计时到 1(而不是显示 0)时更新文本。目前的编写方式永远不会(很少)更新计时器文本。
(您可能希望将持续时间更改为 500 - 原因是我已经 posted 您可能永远不会看到“9”(计时器实现方式的副作用) - 更频繁地更新只是意味着在某些情况下它将更新为相同的文本。)
这可能无法解决您提到的所有问题,但这应该有所帮助 - post 进行此更新后的任何遗留问题:
private void startTimer() {
// stop timer 10 seconds in future - provide updates after 1s and every 1s until
// complete. Change the 1000 (in constructor) to 500 for more consistent UI update results.
countDown = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
// milliseconds (1000 in 1 sec) - update text if at least 1s remaining.
if (millisUntilFinished > 1000) {
timer.setText(String.valueOf(millisUntilFinished/1000));
}
}
@Override
public void onFinish() {
changeQuestion();
}
};
countDown.start();
}
此 展示了对 10 秒计时器的粗略期望,以便更好地理解其行为。
您尝试过使用 AsyncTask 吗?
public class TareaInternet extends AsyncTask<String, Float, String>
它通常解决定时器的问题。
the app doesn't even show it, it stays stuck on 10
在 changeQuestion()
中,也许将参数从 10 更改为 0 会得到您需要的。
timer.setText(String.valueOf(0));
我目前正在开发一个简单的测验应用程序,我尝试使用一个计时器,它只允许您在 10 秒内回答问题,然后再转到下一个问题。 虽然,计时器没有按我想要的方式工作。大约 5 秒后问题发生变化,但应用程序甚至没有显示它,它一直停留在 10,如下所示:
这是 QuestionActivity class:
的代码package com.example.myquiz;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.Animator;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
@RequiresApi(api = Build.VERSION_CODES.O)
public class QuestionActivity extends AppCompatActivity implements View.OnClickListener {
private TextView question, qCount, timer;
private Button option1, option2, option3, option4;
private List<Question> questionList;
private int quesNum;
private CountDownTimer countDown;
private int score;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question);
question = findViewById(R.id.question);
qCount = findViewById(R.id.quest_num);
timer = findViewById(R.id.countdown);
option1 = findViewById(R.id.option1);
option2 = findViewById(R.id.option2);
option3 = findViewById(R.id.option3);
option4 = findViewById(R.id.option4);
option1.setOnClickListener(this);
option2.setOnClickListener(this);
option3.setOnClickListener(this);
option4.setOnClickListener(this);
getQuestionsList();
score = 0;
}
private void getQuestionsList() {
questionList = new ArrayList<>();
questionList.add(new Question("Question1", "A", "B", "C", "D", 2));
questionList.add(new Question("Question2", "B", "B", "D", "A", 2));
questionList.add(new Question("Question3", "C", "B", "A", "D", 2));
questionList.add(new Question("Question4", "A", "D", "C", "B", 2));
questionList.add(new Question("Question5", "C", "D", "A", "D", 2));
setQuestion();
}
private void setQuestion() {
timer.setText(String.valueOf(10));
question.setText(questionList.get(0).getQuestion());
option1.setText(questionList.get(0).getOptionA());
option2.setText(questionList.get(0).getOptionB());
option3.setText(questionList.get(0).getOptionC());
option4.setText(questionList.get(0).getOptionD());
qCount.setText(String.valueOf(1) + "/" + String.valueOf(questionList.size()));
startTimer();
quesNum = 0;
}
private void startTimer() {
countDown = new CountDownTimer(12000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
if (millisUntilFinished < 10)
timer.setText(String.valueOf(millisUntilFinished/1000));
}
@Override
public void onFinish() {
changeQuestion();
}
};
countDown.start();
}
@Override
public void onClick(View v) {
int selectedOption = 0;
switch (v.getId()) {
case R.id.option1:
selectedOption = 1;
break;
case R.id.option2:
selectedOption = 2;
break;
case R.id.option3:
selectedOption = 3;
break;
case R.id.option4:
selectedOption = 4;
break;
default:
}
countDown.cancel();
checkAnswer(selectedOption, v);
}
private void checkAnswer(int selectedOption, View view) {
if (selectedOption == questionList.get(quesNum).getCorrectAns()) {
//Right Answer
((Button) view).setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
score++;
} else {
//Wrong Answer
((Button) view).setBackgroundTintList(ColorStateList.valueOf(Color.RED));
switch (questionList.get(quesNum).getCorrectAns()) {
case 1:
option1.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
case 2:
option2.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
case 3:
option3.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
case 4:
option4.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
break;
}
}
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
changeQuestion();
}
}, 2000);
}
private void changeQuestion() {
if (quesNum < questionList.size() - 1) {
quesNum++;
playAnim(question, 0, 0);
playAnim(option1, 0, 1);
playAnim(option2, 0, 2);
playAnim(option3, 0, 3);
playAnim(option4, 0, 4);
qCount.setText(String.valueOf(quesNum + 1) + "/" + String.valueOf(questionList.size()));
timer.setText(String.valueOf(10));
startTimer();
} else {
//Go to Score Activity
Intent intent = new Intent(QuestionActivity.this, ScoreActivity.class);
intent.putExtra("SCORE",String.valueOf(score) + "/" + String.valueOf(questionList.size()));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
QuestionActivity.this.finish();
}
}
private void playAnim(View view, final int value, int viewNum) {
view.animate().alpha(value).scaleX(value).scaleY(value).setDuration(500).setStartDelay(100).setInterpolator(new DecelerateInterpolator()).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (value == 0) {
switch (viewNum) {
case 0:
((TextView) view).setText(questionList.get(quesNum).getQuestion());
break;
case 1:
((Button) view).setText(questionList.get(quesNum).getOptionA());
break;
case 2:
((Button) view).setText(questionList.get(quesNum).getOptionB());
break;
case 3:
((Button) view).setText(questionList.get(quesNum).getOptionC());
break;
case 4:
((Button) view).setText(questionList.get(quesNum).getOptionD());
break;
}
if (viewNum != 0)
((Button) view).setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#e8c1e1")));
playAnim(view, 1, viewNum);
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
countDown.cancel();
}
}
我该如何解决?
您的 onTick
有一个问题 - 我假设您希望它在倒计时到 1(而不是显示 0)时更新文本。目前的编写方式永远不会(很少)更新计时器文本。
(您可能希望将持续时间更改为 500 - 原因是我已经 posted 您可能永远不会看到“9”(计时器实现方式的副作用) - 更频繁地更新只是意味着在某些情况下它将更新为相同的文本。)
这可能无法解决您提到的所有问题,但这应该有所帮助 - post 进行此更新后的任何遗留问题:
private void startTimer() {
// stop timer 10 seconds in future - provide updates after 1s and every 1s until
// complete. Change the 1000 (in constructor) to 500 for more consistent UI update results.
countDown = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
// milliseconds (1000 in 1 sec) - update text if at least 1s remaining.
if (millisUntilFinished > 1000) {
timer.setText(String.valueOf(millisUntilFinished/1000));
}
}
@Override
public void onFinish() {
changeQuestion();
}
};
countDown.start();
}
此
您尝试过使用 AsyncTask 吗?
public class TareaInternet extends AsyncTask<String, Float, String>
它通常解决定时器的问题。
the app doesn't even show it, it stays stuck on 10
在 changeQuestion()
中,也许将参数从 10 更改为 0 会得到您需要的。
timer.setText(String.valueOf(0));