質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

1328閲覧

for文を使ったCountDownTimerの作り方がわかりません

Jhon_McClane

総合スコア48

iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2020/05/08 02:18

編集2020/05/12 14:21

前提・実現したいこと

イメージ説明

CountDownTimerを利用してstartボタンを押すとタイマー(~秒)が起動し、終わったらカウントを1減らして再びタイマーを起動し、カウントが0になったところでセット数を1減らしカウントを4に戻すことを繰り返しセット数が0になるまで続けたい。
for文を使って上手く作りたいのですがどこに入れればよいかわかりません。
拙いコードですが実現に向けての改善すべきところを教えていただけますか。

※気になるところ(下のソースコード)
ここに記述した処理を繰り返し前のtimer処理が終わった段階で呼びたい

該当のソースコード

package com.example.workouttimer; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import java.util.Locale; public class CountDownTimer extends AppCompatActivity implements View.OnClickListener { private TextView tvTimeLeft, mSetNumber, mCountNumber; private Button mButtonStartStop, mButtonReset; private android.os.CountDownTimer mCountDownTimer; private ProgressBar pb; private final static int ONE_SECOND = 1000; private String name; private int workout_time; private int rest_time; private int set_count; private int set_number; private int set_during; private boolean mTimerRunning = false; private long mStartTimeInMillis; private long mEndTime; private long mTimeLeftInMillis;// TimeLeft:残り時間 Millisecond:ミリ秒 略してる  private int progressStatus = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_count_down_timer); tvTimeLeft = findViewById(R.id.timeLeft); mButtonStartStop = findViewById(R.id.button_start_stop); mButtonReset = findViewById(R.id.button_reset); mSetNumber = findViewById(R.id.setNumber); mCountNumber = findViewById(R.id.countNumber); //データベースからトレーニングの中身を取得する Intent intent = getIntent(); int id = intent.getIntExtra("id", 0); Cursor cursor = NewListItemActivity.mSQLiteHelper.getData("SELECT * FROM WORKOUTLIST WHERE id=" + id); while (cursor.moveToNext()) { name = cursor.getString(1); workout_time = cursor.getInt(2);//トレーニング時間 rest_time = cursor.getInt(3);//休憩時間 set_count = cursor.getInt(4);//カウント set_number = cursor.getInt(5);//セット数 set_during = cursor.getInt(6);//セット間の休憩時間 } pb = findViewById(R.id.pb); setTimeAndProgress(workout_time, workout_time * 1000); mCountNumber.setText(String.valueOf(set_count)); mSetNumber.setText(String.valueOf(set_number)); mButtonStartStop.setOnClickListener(this); mButtonReset.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button_start_stop: if (mTimerRunning) { pauseTimer(); } else { startTimer(); } break; case R.id.button_reset: resetTimer(); break; default: break; } } private void setTimeAndProgress(int progress, long millisecond) { mStartTimeInMillis = millisecond;// セットで受け取った時間をmStartTimeInMillis(開始時間)に格納 mTimeLeftInMillis = mStartTimeInMillis; int progressBarMaximumValue = progress * 2; //Set ProgressBar maximum value pb.setMax(progressBarMaximumValue); updateFontText(); // resetTimer(); } private void resetTimer() { mTimeLeftInMillis = mStartTimeInMillis; //残り時間に格納 progressStatus = 0;//初期値 pb.setProgress(progressStatus); updateFontText(); updateWatchInterface(); } private void pauseTimer() { mCountDownTimer.cancel(); mTimerRunning = false; updateWatchInterface(); } //原因 private void startTimer() { for (int i = set_number; 0 < i; i--) {//3 for (int j = set_count; 0 < j; j--) {//4 mEndTime = System.currentTimeMillis() + mTimeLeftInMillis; mCountDownTimer = new android.os.CountDownTimer(mTimeLeftInMillis, 500) { @Override public void onTick(long millisUntilFinished) { mTimeLeftInMillis = millisUntilFinished; updateFontText(); progressStatus += 1; pb.setProgress(progressStatus); } @Override public void onFinish() { mTimerRunning = false; mButtonStartStop.setText("Start"); updateWatchInterface(); } }.start(); mTimerRunning = true; updateWatchInterface(); } } } //残り時間から表示するテキストのフォントスタイルを決める private void updateFontText() { int minutes = (int) ((mTimeLeftInMillis / 1000) % 3600) / 60; int seconds = (int) (mTimeLeftInMillis / 1000) % 60; String timeLeftFormatted; if (minutes > 0) { timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds); } else { timeLeftFormatted = String.format(Locale.getDefault(), "%02d", seconds); } tvTimeLeft.setText(timeLeftFormatted);//<-second }     //条件によってボタンの出現を切り替える private void updateWatchInterface() { if (mTimerRunning) {//true mButtonReset.setVisibility(View.INVISIBLE); mButtonStartStop.setText("Stop"); } else {//false mButtonReset.setVisibility(View.VISIBLE); mButtonStartStop.setText("Start"); if (mTimeLeftInMillis < 1000) { mButtonStartStop.setVisibility(View.INVISIBLE);//残り時間が1秒を切ったらstart/stopボタンを見えなくする } else { mButtonStartStop.setVisibility(View.VISIBLE);//それ以外start/stopボタンを見える } if (mTimeLeftInMillis < mStartTimeInMillis) { mButtonReset.setVisibility(View.VISIBLE); } else { mButtonReset.setVisibility(View.INVISIBLE); } } } }
変更箇所 private void showWorkout(Workout workout) { countTextView.setText(""+workout.getCount()); setTextView.setText(""+workout.getSet()); // progressBar.setProgress(workout.getTick()); ObjectAnimator animation = ObjectAnimator.ofInt(progressBar,"progress",workout.getTick()); animation.setDuration(500); // 0.5 secondかけて実行する animation.start(); int left = workout.getLeftSecond(); int minute = left / 60; int second = left % 60; lefttimeTextView.setText(String.format((minute>0?"%1$02d:":"")+"%2$02d", minute, second)); } int getTick() { return currentTick; }//書き換え void start(Listener listener) { this.listener = listener; long millisInFuture = (tick+tickMax*(count*set-1))*1000L/PARTICLE_SIZE; countDownTimer = new CountDownTimer(millisInFuture, 1000L/PARTICLE_SIZE) { //[ms] @Override public void onTick(long millisUntilFinished) { tick --; currentTick++; if(tick < 0) { tick = tickMax -1;//切り替わったときに一秒増えないように調整 currentTick = 1;//tuiki if(--count <= 0) { set --; count = countMax; } } Workout.this.listener.progress(Workout.this); } @Override public void onFinish() { currentTick = 0;//追記 tick = 0; count = 0; set = 0; Workout.this.listener.finish(Workout.this); Workout.this.listener = null; } }.start(); listener.start(Workout.this); }

試したこと

private void active() {
for (int i = set_number; 0 < i; i--) {//3
for (int j = set_count; 0 < j; j--) {//4
startTimer();
}
}
}
をonClickでstartTimer();を呼ぶ代わりにactive();を呼んでみたが
思い通りにならなかった。

補足情報(FW/ツールのバージョンなど)

android studio 3.6.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2020/05/08 04:18

for の中で timer を起動すると、ループを回った回数分だけ timer が並行して走ることになりますが、やりたいことは一つの timer が終わったら次の timer を起動することを何回か繰り返すことでは?
Jhon_McClane

2020/05/08 06:49

はいそうです。 並行はしないでタイマーはひとつだけ動いている状態にしたいです
jimbe

2020/05/09 07:19

レイアウトXMLもご提示頂いて宜しいでしょうか.
Jhon_McClane

2020/05/10 01:46 編集

レイアウトを追加したかったのですが10000字を越えてしまい投稿できないとなったため記述いたしませんでした。
jimbe

2020/05/10 01:51

了解です.
guest

回答1

0

ベストアンサー

for文を使って上手く作りたい

ということですが, 「動作を繰り返す」からといってなんでも for で書けるわけではありません.
for は言わば食事に出た納豆を何回かき混ぜるかといった小さな繰り返しであり, されようとしているのは一日 3 回食事を摂ることを一週間繰り返すというレベルで, for で書くような"大きさ"ではありません.

またタイマーですが, 一々カウントやセットが減る度にタイマーを停止・起動せずとも, 逆に一連のカウントダウンの中でカウントやセットを適宜減らしていけば良いだけではないでしょうか.
60 秒を3回ずつ4セットであれば, 60×3×4=計720秒のタイマーの中で60秒毎にカウントを減らし, カウントが0になったら戻してセットを減らすという感じです.

java

1package com.teratail.q259715; 2//package com.example.workouttimer; 3 4import androidx.appcompat.app.AppCompatActivity; 5 6import android.content.Intent; 7import android.os.*; 8import android.view.View; 9import android.widget.Button; 10import android.widget.ProgressBar; 11import android.widget.TextView; 12 13public class CountDownTimerActivity extends AppCompatActivity implements Workout.Listener { 14 private TextView setTextView, countTextView, statusTextView, lefttimeTextView; 15 private ProgressBar progressBar; 16 private Button startStopButton, resetButton; 17 private View.OnClickListener onStartListener, onStopListener; 18 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_count_down_timer); 23 24 //データベースからトレーニングの中身を取得する 25 Intent intent = getIntent(); 26 int id = intent.getIntExtra("id", 0); 27 final Workout workout = getWorkout(id); 28 29 setTextView = findViewById(R.id.setNumber); 30 countTextView = findViewById(R.id.countNumber); 31 statusTextView = findViewById(R.id.status); 32 lefttimeTextView = findViewById(R.id.timeLeft); 33 34 progressBar = findViewById(R.id.pb); 35 36 startStopButton = findViewById(R.id.button_start_stop); 37 38 resetButton = findViewById(R.id.button_reset); 39 resetButton.setOnClickListener(new View.OnClickListener() { 40 @Override 41 public void onClick(View v) { 42 reset(workout); 43 } 44 }); 45 46 onStartListener = new View.OnClickListener() { 47 @Override 48 public void onClick(View v) { 49 workout.start(CountDownTimerActivity.this); 50 } 51 }; 52 onStopListener = new View.OnClickListener() { 53 @Override 54 public void onClick(View v) { 55 workout.stop(); 56 } 57 }; 58 59 reset(workout); 60 } 61 62 private Workout getWorkout(int id) { 63 return new Workout("test",10,5,2,2,20); //テスト用 64 /* 65 try (Cursor cursor = NewListItemActivity.mSQLiteHelper.getData("SELECT * FROM WORKOUTLIST WHERE id=" + id);) { 66 while(cursor.moveToNext()) { 67 String name = cursor.getString(1); 68 int workout_time = cursor.getInt(2); 69 int rest_time = cursor.getInt(3); 70 int set_count = cursor.getInt(4); 71 int set_number = cursor.getInt(5); 72 int set_during = cursor.getInt(6); 73 return new Workout(name,workout_time,rest_time,set_count,set_number,set_during); 74 } 75 } 76 throw new IllegalArgumentException("データがありません. id="+id); 77 */ 78 } 79 80 private void showWorkout(WorkoutProperties properties) { 81 countTextView.setText(""+properties.getCount()); 82 setTextView.setText(""+properties.getSet()); 83 statusTextView.setText(""+properties.getStatus()); 84 85 if(progressBar.getMax() != properties.getTickMax()) { 86 progressBar.setMax(properties.getTickMax()); 87 } 88 progressBar.setProgress(properties.getTickMax() - properties.getTick()); 89 90 int left = properties.getLeftSecond(); 91 int minute = left / 60; 92 int second = left % 60; 93 lefttimeTextView.setText(String.format((minute>0?"%1$02d:":"")+"%2$02d", minute, second)); 94 } 95 96 private void reset(Workout workout) { 97 workout.reset(); 98 showWorkout(workout); 99 100 setStart(); 101 startStopButton.setEnabled(true); 102 resetButton.setEnabled(false); 103 } 104 105 @Override 106 public void start(WorkoutProperties properties) { 107 setStop(); 108 startStopButton.setEnabled(true); 109 resetButton.setEnabled(false); 110 } 111 112 @Override 113 public void progress(WorkoutProperties properties) { 114 showWorkout(properties); 115 } 116 117 @Override 118 public void finish(WorkoutProperties properties) { 119 showWorkout(properties); 120 startStopButton.setEnabled(false); 121 resetButton.setEnabled(true); 122 } 123 124 @Override 125 public void stop(WorkoutProperties properties) { 126 setRestart(); 127 startStopButton.setEnabled(true); 128 resetButton.setEnabled(true); 129 } 130 131 private void setStart() { 132 startStopButton.setText("Start"); 133 startStopButton.setOnClickListener(onStartListener); 134 } 135 private void setRestart() { 136 startStopButton.setText("Restart"); 137 startStopButton.setOnClickListener(onStartListener); 138 } 139 private void setStop() { 140 startStopButton.setText("Stop"); 141 startStopButton.setOnClickListener(onStopListener); 142 } 143}

java

1package com.teratail.q259715; 2 3import android.os.Handler; 4 5import java.util.*; 6 7interface WorkoutProperties { 8 int getSet(); 9 int getCount(); 10 int getTick(); 11 int getTickMax(); 12 int getLeftSecond(); 13 Workout.Status getStatus(); 14} 15 16class Workout implements WorkoutProperties { 17 interface Listener { 18 void start(WorkoutProperties properties); 19 void progress(WorkoutProperties properties); 20 void finish(WorkoutProperties properties); 21 void stop(WorkoutProperties properties); 22 } 23 enum Status { 24 Nonexecution, Training, RestCounts, RestSets 25 } 26 27 private static final int PARTICLE_SIZE = 20; //1秒を何tickに分けるか 28 29 private String name; 30 private int time; //トレーニング時間[s] 31 private int rest_counts; //休憩時間[s] 32 private int countMax; //カウント 33 private int setMax; //セット数 34 private int rest_sets; //セット間の休憩時間[s] 35 36 private Listener listener; 37 private Timer timer; 38 private int tick, tickMax; 39 private int count, set; 40 private Status status; 41 private Handler handler; 42 43 /** 44 * 45 * @param name トレーニング名? 46 * @param time トレーニング時間[s] 47 * @param rest_counts 休憩時間[s] 48 * @param count カウント 49 * @param set セット数 50 * @param rest_sets セット間の休憩時間[s] 51 */ 52 Workout(String name, int time, int rest_counts, int count, int set, int rest_sets) { 53 this.name = name; 54 this.time = time; 55 this.rest_counts = rest_counts; 56 this.countMax = count; 57 this.setMax = set; 58 this.rest_sets = rest_sets; 59 60 this.handler = new Handler(); 61 62 reset(); 63 } 64 65 public int getSet() { return set; } 66 public int getCount() { return count; } 67 public int getTick() { return tick; } 68 public int getTickMax() { return tickMax; } 69 public int getLeftSecond() { return calcLeftSecond(tick); } 70 public Status getStatus() { return status; } 71 72 private static int calcLeftSecond(int tick) { return (tick + PARTICLE_SIZE - 1) / PARTICLE_SIZE; } 73 74 synchronized void start(Listener listener) { 75 if(timer != null) throw new IllegalStateException(); 76 this.listener = listener; 77 status = Status.Training; 78 listener.start(Workout.this); 79 timer = new Timer(); 80 timer.scheduleAtFixedRate(new TickTask(), 1000L / PARTICLE_SIZE, 1000L / PARTICLE_SIZE); //[ms] 81 } 82 83 private class TickTask extends TimerTask { 84 @Override 85 public void run() { 86 boolean finish = downTick(); 87 final WorkoutProperties properties = new WorkoutSnapshot(Workout.this); 88 handler.post(new Runnable() { 89 public void run() { 90 postProgress(properties); 91 } 92 }); 93 if(finish) { 94 synchronized(this) { 95 timer.cancel(); 96 timer = null; 97 } 98 handler.post(new Runnable() { 99 public void run() { 100 postFinish(properties); 101 } 102 }); 103 } 104 } 105 } 106 107 private boolean downTick() { 108 if(--tick > 0) return false; 109 110 switch(status) { 111 case RestCounts: 112 if(count <= 0) { 113 status = Status.RestSets; 114 tickMax = rest_sets * PARTICLE_SIZE; 115 tick = tickMax; 116 break; 117 } 118 /*break;*/ 119 case RestSets: 120 status = Status.Training; 121 if(count <= 0) count = countMax; 122 tickMax = time * PARTICLE_SIZE; 123 tick = tickMax; 124 break; 125 default: //Training 126 if(--count <= 0) { 127 if(--set <= 0) { 128 status = Status.Nonexecution; 129 return true; //finish 130 } 131 } 132 status = Status.RestCounts; 133 tickMax = rest_counts * PARTICLE_SIZE; 134 tick = tickMax; 135 } 136 return false; 137 } 138 139 private static class WorkoutSnapshot implements WorkoutProperties { 140 private int tick, tickMax; 141 private int count, set; 142 private Status status; 143 144 WorkoutSnapshot(Workout wo) { 145 this.tick = wo.tick; 146 this.tickMax = wo.tickMax; 147 this.count = wo.count; 148 this.set = wo.set; 149 this.status = wo.status; 150 } 151 152 public int getSet() { return set; } 153 public int getCount() { return count; } 154 public int getTick() { return tick; } 155 public int getTickMax() { return tickMax; } 156 public int getLeftSecond() { return calcLeftSecond(tick); } 157 public Status getStatus() { return status; } 158 } 159 160 private synchronized void postProgress(WorkoutProperties properties) { 161 if(listener != null) { 162 listener.progress(properties); 163 } 164 } 165 166 private synchronized void postFinish(WorkoutProperties properties) { 167 if(listener != null) { 168 listener.finish(properties); 169 listener = null; 170 } 171 } 172 173 synchronized void stop() { 174 if(timer != null) { 175 timer.cancel(); 176 timer = null; 177 if(listener != null) { 178 listener.stop(this); 179 listener = null; 180 } 181 } 182 } 183 184 synchronized void reset() { 185 if(timer == null) { 186 count = countMax; 187 set = setMax; 188 tickMax = time * PARTICLE_SIZE; 189 tick = tickMax; 190 status = Status.Nonexecution; 191 } 192 } 193}

投稿2020/05/09 18:58

編集2020/05/14 20:00
jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Jhon_McClane

2020/05/10 03:11

progressBar.setMax(workout.getTickMax()); ここで中身がnullといわれています。 tickMaxの値はWorkoutをインスタンス化した時点で初期化されて値が入っていると思うのですがなぜこのようなエラーが起きているのでしょうか Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ProgressBar.setMax(int)' on a null object reference at com.example.workouttimer.CountDownTimer.onCreate(CountDownTimer.java:36)
jimbe

2020/05/10 04:12

言われているのは「workout.getTickMax()」では無く「progressBar.setMax()」のほうです. progressBar = findViewById(R.id.pb); での id が合っていないのではないでしょうか. レイアウトの id に合わせてください.
Jhon_McClane

2020/05/10 07:11 編集

レイアウトのProgressBarのidはpbで合っていました。
jimbe

2020/05/10 11:51

progressBar = findViewById(R.id.pb); で progressBar が null になっていないかご確認ください. もしこのコードの為に activity_main.xml に activity_count_down_timer.xml をコピーするなどしていると, id が重なってしまっているかもしれません. こちらのコードの setContentView(R.layout.activity_main) を setContentView(R.layout.activity_count_down_timer) とする等してみてください.
Jhon_McClane

2020/05/10 14:29

setContentView(R.layout.activity_main) を setContentView(R.layout.activity_count_down_timer) に直したところ解決しました。 まだまだ自分の知らないところが多くあり全部のコードを把握できていませんので終わったらベストアンサーにしようと考えています。申し訳ありませんが、遅くなるかもしれません。 また気になるところがあったら質問するかもしれません。そのときはよろしくお願いします。
jimbe

2020/05/11 04:28

何か時間制限があるわけではありませんし, 私のコードに対するご質問であれば例えベストアンサーの後でも構いません. 一応カウントダウンという点だけ確認していますが, 表示のイメージやボタンの動作等々でお考えのモノと異なるかもしれません. ですので回答のコードでも弄って頂いて構いませんが, もしその過程でご質問される場合は, どこをどう変更しているのかのご提示も合わせてお願い致します.
jimbe

2020/05/11 04:31 編集

setContentView を変えているのを書いていませんでした. お手数おかけしてすいません. (コメントを書いている内にこの文が消えてしまいました.)
Jhon_McClane

2020/05/11 14:36

teratailはベストアンサーを出した後でも質問などを継続することができるのでしょうか。
jimbe

2020/05/11 15:27

ベストアンサーで解決済みという表示にはなりますが, 質問の編集や回答・コメントなどが出来なくなることは無いようです.
Jhon_McClane

2020/05/12 14:17

タイマーのprogressの値を0から終わり(時計回り)に変更するため無理矢理currentTickを追加しました。一様思い通りにいったのですがこれで大丈夫ですか。 また最初にスタートボタンを押したターンは1秒短くなることに気づいたのですがどのように改善すればよいでしょうか。 progressの滑らかに行いたいと思い手探りで進めているのですが、反時計回りで動いてしまったり、途中で止まったりと思うようにいきません。
jimbe

2020/05/12 16:00

progress の向きを逆にするのでしたら, progressBar.setProgress(workout.getTick()); を progressBar.setProgress(workout.getTickMax() - workout.getTick()); とすれば逆になります. 「最初にスタートボタンを押したターン」というのは, start を押してから 最初に count が減るまでの間でしょうか? それは Jhon_McClane さんの currentTick 追加前でしょうか. ObjectAnimator の 3行を追加して試してみましたが, エミュレータの所為なのか分かりませんが動作が不安定でした. ObjectAnimator の使用方法につきましては私もまだよく分かっておりませんが, もっと細かくプログレスバーの表示を更新したいのでしたら, Workout クラスの private static final int PARTICLE_SIZE = 2; //1秒を何tickに分けるか の値を調整してみてください. 10 倍の 20 にすれば 1 秒に 20 tick が発生するようになりますので, 結構細かくなるかと思います.
Jhon_McClane

2020/05/13 06:39

最初にスタートボタンを押したターンは1秒短くなるとなると述べたのですが タイマーが回ったとき最後に0秒が表示されるのでなく 例えばタイマーが3秒で繰り返されたときスタートボタンを押し3秒から2.0001秒までは03の表示にし 2秒から1.0001秒までを02の表示、1秒から0秒を01の表示にしたいと考えています。 現在の表示状況は02->01->00となっているので個々を直したいでえす。
Jhon_McClane

2020/05/13 06:55 編集

CountDownTimerクラスのshowWorkoutメソッドのsecondを (left % 60)から(left % 60 + 1)に変更しました。 タイマーを起動する前(startボタンを押す前)だけ1秒多く表示されてしまいます。 一度起動すると後は上手くいくので初期状態だけ表示を変えたいです。
jimbe

2020/05/13 07:54

なるほど, count3で3秒毎だと start を押すと (count=3)2-1-0-(count=2)2-1-0... となっているのを, (count=3)3-2-1-(count=2)3-2-1... という表示になるようにということですね.
Jhon_McClane

2020/05/13 08:10

はい、そのように実装したいと考えています。 また、最終的に作り上げたいものはトレーニング時間のtimeが終わった後にカウントを1減らし、次のトレーニングに行く前に休憩(rest_time)をはさみ、カウントが0になるまで繰り返す。次にセットを1減らし、トレーニングに行く前にセット間の休憩(during_time)を挟みたいと考えています。 カウントが減ったらresut_time -> トレーニングtime セットが減ったら rest_time -> during_time -> トレーニングtimeという流れにしたいです。
jimbe

2020/05/13 09:07

同時に二つ以上のことを考えると大変ですので, 今のところは休憩のことはイメージのみとしまして. トレーニング時間のカウントダウンの表示に集中されたほうが良いかと思います. Workout クラスを修正してみました. > CountDownTimerクラスのshowWorkoutメソッドのsecondを (left % 60)から(left % 60 + 1)に変更 は必要ありません. Workout#getLeftSecond が適切な値を返すはずです. また, workout#Listener の progress を呼ぶタイミングを変更しました. CountDownTimer の onTick 時に呼んでいましたが, onTick は開始直後から呼ばれ, また終了時は呼ばれません. これは tick の始まりに呼ばれるというイメージですが, 分かり難いので, progress は開始直後の onTick では呼ばないようにし, 終了時は呼ぶようにしました. これにより, progress は tick の終わりに呼ばれるようなイメージになりますので, カウントダウンのタイミングに一致します.
Jhon_McClane

2020/05/13 10:23

セット数1、カウントが1になり最後のカウントダウンが行われる際、progressBarが最後まで届きません。
jimbe

2020/05/13 13:54 編集

確認しました. PARTICLE_SIZE を 2 にすると 0 までいきますね...どうやら PARTICLE_SIZE を 20 にすると tick=5 ぐらいまでしか onTick が呼ばれないようです. CountDownTimer だと精度はこの程度ということでしょうか. CountDownTimer では無くTimer#schedule もしくは scheduleAtFixedRate ではどうなるか試してみます.
jimbe

2020/05/13 15:55

CountDownTimer を止めて Timer#scheduleAtFixedRate を使うようにしました. その為 Listener の呼び出しが Handler 経由となり, Stop や Reset との兼ね合いから Syncronized を使っています. また, Listener の各メソッドの引数型を Workout から WorkoutProperties に変更していますので, 実装しているアクティビティ側の変更と, showWorkout の引数も WorkoutProperties に変更してください. 今のところこちらではこれで PARTICLE_SIZE = 20 でも動作しています.
Jhon_McClane

2020/05/14 15:00

jimbeさん、ありがとうございます。 動きました!!
jimbe

2020/05/14 20:07

では, rest_counts/rest_sets を入れてみたコードに修正しました. 確認のため, レイアウトに @+id/status の TextView を追加して, WorkoutProperties に 追加した getStatus() メソッドの値を表示しています.
Jhon_McClane

2020/05/15 13:22

ありがとうございます。すごく実現したかったことができました。 まだアプリとしては他に付け足したい機能がいくつかあり作っていく段階でわからなくなったらこの場で質問させていただきます。
Jhon_McClane

2020/05/15 14:21 編集

バイブレーションを付け足したいのですがWorkoutクラスで vib = (Vibrator)getSystemService(VIBRATOR_SERVICE);を書くと、 getSystemServiceが認識されません。Activityのあるクラスで記述したところエラーは起こらなかったのでこれはActivityクラスでないとかけないのでしょうか。 timerが0になるごとに呼ぼうと考えています。
jimbe

2020/05/15 15:21

念のため, > ~この場で質問させていただきます の「この場」は teratail ということで宜しいでしょうか. 一応このコメント欄は『for文を使ったCountDownTimerの作り方がわかりません』というご質問に対する回答のコメントでして, 作成されているというアプリの開発を手伝う場ではありません. コードを役立てて頂けるのはありがたいですが, どこまで実装してあってもあくまでサンプルであって, アプリに組み込まれたモノは私のコードでは無く Jhon_McClane さんのコードになります. このご質問としては解決となったようですし, 別の問題が発生しましたら別のご質問をされたほうが宜しいかと思います. なお, getSystemService メソッドは Activity クラスのメソッドですので, Activity ではない Workout にはありません.
Jhon_McClane

2020/05/16 03:26

わかりました。 この質問はこれで終わらせていただきます
Jhon_McClane

2020/05/27 09:25

上に質問を終了すると述べたのですが、解決できないため質問します android の下にある戻るボタンを押したときに実行していた処理(timer)が動いている状態です。 再びCountDownTimerのActivityに入りstartボタンを押すと後ろの処理は前のが継続されて動いている状態です。 今のところ問題はないのですが、裏で動いてしまっている無駄な処理を止めたいです。 戻るを押したらリセットされている状態にしたいです。
jimbe

2020/05/30 08:18

Android の"戻る"ボタンによってアプリが裏に回った場合や再度アプリを表示させた場合等では, Activity の onPause / onResume といったメソッドが OS から呼ばれます. ( Activity の"ライフサイクル"として決まっていますので, お調べになってみてください.) Activity が裏に回った場合は onPause が呼ばれますので, onPause メソッドを定義し, その中で動いている各タイマーを停止させてください.
Jhon_McClane

2020/06/04 02:19

わかりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問