안녕하세요~ 두결입니다.
지난시간에는 4단계까지 해보았는데요~
이번시간에는
5단계로 가기전에 30초 시간제한 기능을 구현해보겠습니다.
▣ 30초 카운트다운 타이머 추가하기
먼저, 30초 카운트다운 타이머를 추가해보겠습니다.
CountDownTimer cdTimer;
// 30초 카운트다운 타이머
private void StartCountDownTimer()
{
// 타이머가 이미 있으면 종료하기
if(cdTimer !=null)
{
cdTimer.cancel();
cdTimer = null;
}
cdTimer = new CountDownTimer(30000,1000) {
@Override
public void onFinish() {
}
@Override
public void onTick(long l) {
}
};
cdTimer.start();
}
cdTimer라는 CountDown Timer를 하나 만들구요~
StartCountDownTimer()함수를 만들어서 여기에서 CountDownTimer를 생성하였습니다.
카운트다운 시간은 30초로 설정하였습니다.
ActivityResultLauncher<Intent> mPopupCountDownForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK) {
// blank 이미지 표시하기
for(int i=0;i<nCurImageCount;i++) {
ImageView imgvCur = arrayListImage.get(i);
FlipCardAnimation(imgvCur);
}
bGameStart =true;
StartCountDownTimer();
}
}
);
새게임 시작하고 5초 카운트다운이 끝난후에 그림카드를 뒤집고 나서
StartCountDownTimer()함수를 호출하였습니다.
카운트 다운이 잘 표시되는지 확인하기 위해서 TextView를 하나추가해보겠습니다.

Main Layout에서 TextView를 하나 추가하구요~
<TextView
android:id="@+id/txtvCountDown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.1" />
ID는 txtvCountDown이라고 하였습니다.
txtv_CountDown = findViewById(R.id.txtvCountDown);
txtv_CountDown.setTextSize(20);
txtv_CountDown.setTypeface(null, Typeface.BOLD);
txtv_CountDown.setGravity(Gravity.CENTER|Gravity.TOP);
txtv_CountDown.setTextColor(Color.parseColor("#FFFFFF"));
txtv_CountDown 객체 생성하고 기본 설정까지 해주었습니다.
cdTimer = new CountDownTimer(30000,1000) {
@Override
public void onFinish() {
}
@Override
public void onTick(long l) {
txtv_CountDown.setText((l / 1000) + "");
}
};
cdTimer.start();
마지막으로 CountDownTimer의 onTick()함수에서 30초 카운트다운하는 숫자를 표시해주었습니다.
여기까지 잘 되는지 실행을 해보면

네 위쪽에 카운트다운하는 숫자가 잘 표시되네요..^^
▣ 30초 카운트다운 소수점 3자리까지 표시하기
먼저, 30초 카운트다운 타이머를 추가해보겠습니다.
소수점 3자리까지 표시하는것은 String.format()을 이용하면 쉽게 할수 있습니다.
// 30초 카운트다운 타이머
private void StartCountDownTimer()
{
// 타이머가 이미 있으면 종료하기
if(cdTimer !=null)
{
cdTimer.cancel();
cdTimer = null;
}
cdTimer = new CountDownTimer(30000,1000) {
@Override
public void onFinish() {
}
@Override
public void onTick(long l) {
String sLeftTime;
sLeftTime = String.format("%.03f",l / 1000.0f);
txtv_CountDown.setText(sLeftTime);
}
};
cdTimer.start();
}
위와같이 String.format("%.03f", l / 1000.0f);를 이용해서
30초중에 남은 시간을 소숫점 3자리로 표시하였습니다.
그런데, 지금 이 카운트다운 타이머가 1초간격으로 바뀌다보니까 약간 역동적이지가 않네요~
타이머간격을 조금 바꾸어보겠습니다.
cdTimer = new CountDownTimer(30000,50) {
네, 위와같이 50ms간격으로 바꾸었습니다.

네, 위와같이 소숫점 3자리까지 표시가 잘 되고.. 50ms간격이라 빠르게 잘 바뀌네요..^^
▣ 30초안에 못맞출 경우, 재도전 창 띄우기
마지막으로 한가지만 더 해보겠습니다.
30초 안에 맞추지 못할 경우에는 재도전 할지 게임을 종료할지를 물어보는 창을 띄워보도록 하겠습니다.
이건 팝업창을 새로 만들지 않고 그냥 간단한 Dialog박스로 해보겠습니다.
// 다시 도전할지 여부 물어보는 Dialog 박스 띄워주는 함수
private void ShowRetryDialog() {
AlertDialog.Builder builderRetryDialog = new AlertDialog.Builder(this);
builderRetryDialog.setTitle("재 도전?");
builderRetryDialog.setMessage("두결 - 그림짝 맞추기 게임을 다시 도전하시겠습니까?");
builderRetryDialog.setPositiveButton("확인", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 확인 버튼 클릭시 동작
NewGame();
}
});
builderRetryDialog.setNegativeButton("취소", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 취소 버튼 클릭시 동작
finishAndRemoveTask();
}
});
builderRetryDialog.setCancelable(false); // 외부 터치로 다이얼로그 닫기 방지
builderRetryDialog.show();
}
ShowRetryDialog()함수를 만들어서
AlertDialog.Builder를 이용해서 간단한 메세지 박스를 띄워보았습니다.
여기에서 확인버튼을 누르면 NewGame()을 호출해서 새로운 게임을 하고
취소버튼을 누르면 앱을 종료하도록 하였습니다.
cdTimer = new CountDownTimer(30000,50) {
@Override
public void onFinish() {
ShowRetryDialog(); // 재도전?
}
@Override
public void onTick(long l) {
String sLeftTime;
sLeftTime = String.format("%.03f",l / 1000.0f);
txtv_CountDown.setText(sLeftTime);
}
};
cdTimer.start();
카운트다운타이머의 onFinish()에서 ShowRetryDialog()함수를 호출하였습니다.
즉, 30초안에 맞추지 못하고 카운트다운이 종료되면 그때 재도전할지를 물어보는 다이얼로그 창을 띄운것이죠..
아, 그리고
30초 안에 맞춘경우에는
// 다음단계 설정 팝업창 띄우는 함수.
private void ShowPopupNextStage()
{
StopCountDownTimer();
Intent intent = new Intent(getApplicationContext(), PopupNextStage.class);
intent.putExtra("curgamestage", nGameStage);
mStartForResult.launch(intent);
}
다음단계 설정 팝업창을 띄우기전에
StopCountDownTimer()함수를 호출해서 30초 카운트 다운 타이머를 멈추도록 하였습니다.
private void StopCountDownTimer()
{
// 타이머가 이미 있으면 종료하기
if(cdTimer !=null)
{
cdTimer.cancel();
cdTimer = null;
}
txtv_CountDown.setText("30.000");
}
네 위와같이 StopCountDownTimer()에서 cdTimer를 종료해주고 30초 숫자 표시해주는 TextView도 초기화 해주었습니다.

네, 위와같이 30초 안에 다 못맞추면 "재도전" Dialog 상자가 표시가 됩니다. ^^
여기까지 전체 동영상으로 한번 보겠습니다.
네 1~4단계까지 잘 되고 30초 안에 못맞추면 재도전 대화상자도 잘 표시가 되네요.. ^^
이번시간은 여기까지만 하도록 하구요~
다음시간에는 저 30초 숫자를 숫자로만 표시하지말고 프로그레스바도 같이 표시해보도록 하겠습니다.
그럼, 이만 ~
감사합니다. ^^
