teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

rest_counts/rest_sets 及び Status 関係を追加

2020/05/14 20:00

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -19,7 +19,7 @@
19
19
  import android.widget.TextView;
20
20
 
21
21
  public class CountDownTimerActivity extends AppCompatActivity implements Workout.Listener {
22
- private TextView setTextView, countTextView, lefttimeTextView;
22
+ private TextView setTextView, countTextView, statusTextView, lefttimeTextView;
23
23
  private ProgressBar progressBar;
24
24
  private Button startStopButton, resetButton;
25
25
  private View.OnClickListener onStartListener, onStopListener;
@@ -36,10 +36,10 @@
36
36
 
37
37
  setTextView = findViewById(R.id.setNumber);
38
38
  countTextView = findViewById(R.id.countNumber);
39
+ statusTextView = findViewById(R.id.status);
39
40
  lefttimeTextView = findViewById(R.id.timeLeft);
40
41
 
41
42
  progressBar = findViewById(R.id.pb);
42
- progressBar.setMax(workout.getTickMax());
43
43
 
44
44
  startStopButton = findViewById(R.id.button_start_stop);
45
45
 
@@ -68,7 +68,7 @@
68
68
  }
69
69
 
70
70
  private Workout getWorkout(int id) {
71
- return new Workout("test",10,0,2,1,0); //テスト用
71
+ return new Workout("test",10,5,2,2,20); //テスト用
72
72
  /*
73
73
  try (Cursor cursor = NewListItemActivity.mSQLiteHelper.getData("SELECT * FROM WORKOUTLIST WHERE id=" + id);) {
74
74
  while(cursor.moveToNext()) {
@@ -88,7 +88,11 @@
88
88
  private void showWorkout(WorkoutProperties properties) {
89
89
  countTextView.setText(""+properties.getCount());
90
90
  setTextView.setText(""+properties.getSet());
91
+ statusTextView.setText(""+properties.getStatus());
91
92
 
93
+ if(progressBar.getMax() != properties.getTickMax()) {
94
+ progressBar.setMax(properties.getTickMax());
95
+ }
92
96
  progressBar.setProgress(properties.getTickMax() - properties.getTick());
93
97
 
94
98
  int left = properties.getLeftSecond();
@@ -159,6 +163,7 @@
159
163
  int getTick();
160
164
  int getTickMax();
161
165
  int getLeftSecond();
166
+ Workout.Status getStatus();
162
167
  }
163
168
 
164
169
  class Workout implements WorkoutProperties {
@@ -168,31 +173,43 @@
168
173
  void finish(WorkoutProperties properties);
169
174
  void stop(WorkoutProperties properties);
170
175
  }
176
+ enum Status {
177
+ Nonexecution, Training, RestCounts, RestSets
178
+ }
171
179
 
172
180
  private static final int PARTICLE_SIZE = 20; //1秒を何tickに分けるか
173
181
 
174
- //private String name;
182
+ private String name;
175
- //private int time; //トレーニング時間[s]
183
+ private int time; //トレーニング時間[s]
176
- //private int rest_time; //休憩時間[s]
184
+ private int rest_counts; //休憩時間[s]
177
185
  private int countMax; //カウント
178
186
  private int setMax; //セット数
179
- //private int set_during; //セット間の休憩時間[s]
187
+ private int rest_sets; //セット間の休憩時間[s]
180
188
 
181
189
  private Listener listener;
182
190
  private Timer timer;
183
191
  private int tick, tickMax;
184
192
  private int count, set;
193
+ private Status status;
185
194
  private Handler handler;
186
195
 
196
+ /**
197
+ *
198
+ * @param name トレーニング名?
199
+ * @param time トレーニング時間[s]
200
+ * @param rest_counts 休憩時間[s]
201
+ * @param count カウント
202
+ * @param set セット数
203
+ * @param rest_sets セット間の休憩時間[s]
204
+ */
187
- Workout(String name, int time, int rest_time, int count, int set, int set_during) {
205
+ Workout(String name, int time, int rest_counts, int count, int set, int rest_sets) {
188
- //this.name = name;
206
+ this.name = name;
189
- //this.time = time;
207
+ this.time = time;
190
- //this.rest_time = rest_time;
208
+ this.rest_counts = rest_counts;
191
209
  this.countMax = count;
192
210
  this.setMax = set;
193
- //this.set_during = set_during;
211
+ this.rest_sets = rest_sets;
194
212
 
195
- this.tickMax = time * PARTICLE_SIZE;
196
213
  this.handler = new Handler();
197
214
 
198
215
  reset();
@@ -203,16 +220,17 @@
203
220
  public int getTick() { return tick; }
204
221
  public int getTickMax() { return tickMax; }
205
222
  public int getLeftSecond() { return calcLeftSecond(tick); }
223
+ public Status getStatus() { return status; }
206
224
 
207
225
  private static int calcLeftSecond(int tick) { return (tick + PARTICLE_SIZE - 1) / PARTICLE_SIZE; }
208
226
 
209
227
  synchronized void start(Listener listener) {
210
- if(timer != null)
211
- throw new IllegalStateException();
228
+ if(timer != null) throw new IllegalStateException();
212
229
  this.listener = listener;
230
+ status = Status.Training;
231
+ listener.start(Workout.this);
213
232
  timer = new Timer();
214
233
  timer.scheduleAtFixedRate(new TickTask(), 1000L / PARTICLE_SIZE, 1000L / PARTICLE_SIZE); //[ms]
215
- listener.start(Workout.this);
216
234
  }
217
235
 
218
236
  private class TickTask extends TimerTask {
@@ -240,12 +258,33 @@
240
258
  }
241
259
 
242
260
  private boolean downTick() {
261
+ if(--tick > 0) return false;
262
+
263
+ switch(status) {
264
+ case RestCounts:
243
- if(--tick <= 0) {
265
+ if(count <= 0) {
266
+ status = Status.RestSets;
267
+ tickMax = rest_sets * PARTICLE_SIZE;
268
+ tick = tickMax;
269
+ break;
270
+ }
271
+ /*break;*/
272
+ case RestSets:
273
+ status = Status.Training;
274
+ if(count <= 0) count = countMax;
275
+ tickMax = time * PARTICLE_SIZE;
276
+ tick = tickMax;
277
+ break;
278
+ default: //Training
244
- if(--count <= 0) {
279
+ if(--count <= 0) {
280
+ if(--set <= 0) {
281
+ status = Status.Nonexecution;
245
- if(--set <= 0) return true; //finish
282
+ return true; //finish
246
- count = countMax;
247
- }
283
+ }
284
+ }
285
+ status = Status.RestCounts;
286
+ tickMax = rest_counts * PARTICLE_SIZE;
248
- tick = tickMax;
287
+ tick = tickMax;
249
288
  }
250
289
  return false;
251
290
  }
@@ -253,12 +292,14 @@
253
292
  private static class WorkoutSnapshot implements WorkoutProperties {
254
293
  private int tick, tickMax;
255
294
  private int count, set;
295
+ private Status status;
256
296
 
257
297
  WorkoutSnapshot(Workout wo) {
258
298
  this.tick = wo.tick;
259
299
  this.tickMax = wo.tickMax;
260
300
  this.count = wo.count;
261
301
  this.set = wo.set;
302
+ this.status = wo.status;
262
303
  }
263
304
 
264
305
  public int getSet() { return set; }
@@ -266,6 +307,7 @@
266
307
  public int getTick() { return tick; }
267
308
  public int getTickMax() { return tickMax; }
268
309
  public int getLeftSecond() { return calcLeftSecond(tick); }
310
+ public Status getStatus() { return status; }
269
311
  }
270
312
 
271
313
  private synchronized void postProgress(WorkoutProperties properties) {
@@ -294,9 +336,11 @@
294
336
 
295
337
  synchronized void reset() {
296
338
  if(timer == null) {
297
- this.count = countMax;
339
+ count = countMax;
298
- this.set = setMax;
340
+ set = setMax;
341
+ tickMax = time * PARTICLE_SIZE;
299
- this.tick = tickMax;
342
+ tick = tickMax;
343
+ status = Status.Nonexecution;
300
344
  }
301
345
  }
302
346
  }

2

CountDownTimer から Timer#scheduleAtFixedRate に変更

2020/05/14 20:00

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -27,7 +27,7 @@
27
27
  @Override
28
28
  protected void onCreate(Bundle savedInstanceState) {
29
29
  super.onCreate(savedInstanceState);
30
- setContentView(R.layout.activity_main); //activity_count_down_timer
30
+ setContentView(R.layout.activity_count_down_timer);
31
31
 
32
32
  //データベースからトレーニングの中身を取得する
33
33
  Intent intent = getIntent();
@@ -68,7 +68,7 @@
68
68
  }
69
69
 
70
70
  private Workout getWorkout(int id) {
71
- return new Workout("test",10,0,3,4,0); //テスト用
71
+ return new Workout("test",10,0,2,1,0); //テスト用
72
72
  /*
73
73
  try (Cursor cursor = NewListItemActivity.mSQLiteHelper.getData("SELECT * FROM WORKOUTLIST WHERE id=" + id);) {
74
74
  while(cursor.moveToNext()) {
@@ -85,12 +85,13 @@
85
85
  */
86
86
  }
87
87
 
88
- private void showWorkout(Workout workout) {
88
+ private void showWorkout(WorkoutProperties properties) {
89
- countTextView.setText(""+workout.getCount());
89
+ countTextView.setText(""+properties.getCount());
90
- setTextView.setText(""+workout.getSet());
90
+ setTextView.setText(""+properties.getSet());
91
- progressBar.setProgress(workout.getTick());
92
91
 
92
+ progressBar.setProgress(properties.getTickMax() - properties.getTick());
93
+
93
- int left = workout.getLeftSecond();
94
+ int left = properties.getLeftSecond();
94
95
  int minute = left / 60;
95
96
  int second = left % 60;
96
97
  lefttimeTextView.setText(String.format((minute>0?"%1$02d:":"")+"%2$02d", minute, second));
@@ -106,26 +107,26 @@
106
107
  }
107
108
 
108
109
  @Override
109
- public void start(Workout workout) {
110
+ public void start(WorkoutProperties properties) {
110
111
  setStop();
111
112
  startStopButton.setEnabled(true);
112
113
  resetButton.setEnabled(false);
113
114
  }
114
115
 
115
116
  @Override
116
- public void progress(Workout workout) {
117
+ public void progress(WorkoutProperties properties) {
117
- showWorkout(workout);
118
+ showWorkout(properties);
118
119
  }
119
120
 
120
121
  @Override
121
- public void finish(Workout workout) {
122
+ public void finish(WorkoutProperties properties) {
122
- showWorkout(workout);
123
+ showWorkout(properties);
123
124
  startStopButton.setEnabled(false);
124
125
  resetButton.setEnabled(true);
125
126
  }
126
127
 
127
128
  @Override
128
- public void stop(Workout workout) {
129
+ public void stop(WorkoutProperties properties) {
129
130
  setRestart();
130
131
  startStopButton.setEnabled(true);
131
132
  resetButton.setEnabled(true);
@@ -148,15 +149,24 @@
148
149
  ```java
149
150
  package com.teratail.q259715;
150
151
 
151
- import android.os.CountDownTimer;
152
+ import android.os.Handler;
152
- import android.util.Log;
153
153
 
154
+ import java.util.*;
155
+
154
- class Workout {
156
+ interface WorkoutProperties {
157
+ int getSet();
158
+ int getCount();
159
+ int getTick();
160
+ int getTickMax();
161
+ int getLeftSecond();
162
+ }
163
+
164
+ class Workout implements WorkoutProperties {
155
165
  interface Listener {
156
- void start(Workout workout);
166
+ void start(WorkoutProperties properties);
157
- void progress(Workout workout);
167
+ void progress(WorkoutProperties properties);
158
- void finish(Workout workout);
168
+ void finish(WorkoutProperties properties);
159
- void stop(Workout workout);
169
+ void stop(WorkoutProperties properties);
160
170
  }
161
171
 
162
172
  private static final int PARTICLE_SIZE = 20; //1秒を何tickに分けるか
@@ -169,10 +179,10 @@
169
179
  //private int set_during; //セット間の休憩時間[s]
170
180
 
171
181
  private Listener listener;
172
- private CountDownTimer countDownTimer;
182
+ private Timer timer;
173
183
  private int tick, tickMax;
174
184
  private int count, set;
175
- private boolean firstTick = false; //CountDownTimer の 最初の onTick を無視するため
185
+ private Handler handler;
176
186
 
177
187
  Workout(String name, int time, int rest_time, int count, int set, int set_during) {
178
188
  //this.name = name;
@@ -183,62 +193,111 @@
183
193
  //this.set_during = set_during;
184
194
 
185
195
  this.tickMax = time * PARTICLE_SIZE;
196
+ this.handler = new Handler();
186
197
 
187
198
  reset();
188
199
  }
189
200
 
190
- int getSet() { return set; }
201
+ public int getSet() { return set; }
191
- int getCount() { return count; }
202
+ public int getCount() { return count; }
192
- int getTick() { return tick; }
203
+ public int getTick() { return tick; }
193
- int getTickMax() { return tickMax; }
204
+ public int getTickMax() { return tickMax; }
194
- int getLeftSecond() { return (tick+PARTICLE_SIZE-1) / PARTICLE_SIZE; }
205
+ public int getLeftSecond() { return calcLeftSecond(tick); }
195
206
 
207
+ private static int calcLeftSecond(int tick) { return (tick + PARTICLE_SIZE - 1) / PARTICLE_SIZE; }
208
+
196
- void start(Listener listener) {
209
+ synchronized void start(Listener listener) {
210
+ if(timer != null)
211
+ throw new IllegalStateException();
197
212
  this.listener = listener;
198
- long millisInFuture = (tick+tickMax*(count*set-1))*1000L/PARTICLE_SIZE;
199
- firstTick = true;
213
+ timer = new Timer();
200
- countDownTimer = new CountDownTimer(millisInFuture, 1000L/PARTICLE_SIZE) { //[ms]
214
+ timer.scheduleAtFixedRate(new TickTask(), 1000L / PARTICLE_SIZE, 1000L / PARTICLE_SIZE); //[ms]
215
+ listener.start(Workout.this);
216
+ }
217
+
218
+ private class TickTask extends TimerTask {
201
- @Override
219
+ @Override
202
- public void onTick(long ignore) {
220
+ public void run() {
203
- if(firstTick) { //最初の onTick を無視
221
+ boolean finish = downTick();
222
+ final WorkoutProperties properties = new WorkoutSnapshot(Workout.this);
223
+ handler.post(new Runnable() {
204
- firstTick = false;
224
+ public void run() {
205
- return;
225
+ postProgress(properties);
206
226
  }
227
+ });
228
+ if(finish) {
229
+ synchronized(this) {
207
- downTick();
230
+ timer.cancel();
231
+ timer = null;
232
+ }
233
+ handler.post(new Runnable() {
234
+ public void run() {
208
- Workout.this.listener.progress(Workout.this);
235
+ postFinish(properties);
236
+ }
237
+ });
209
238
  }
210
- @Override
211
- public void onFinish() {
212
- onTick(0L); //終了時の Tick を発生(したように見せかける)
213
- Workout.this.listener.finish(Workout.this);
214
- Workout.this.listener = null;
215
- }
239
+ }
216
- }.start();
217
- listener.start(Workout.this);
218
240
  }
241
+
219
- private void downTick() {
242
+ private boolean downTick() {
220
243
  if(--tick <= 0) {
221
244
  if(--count <= 0) {
222
- if(--set <= 0) return; //finish
245
+ if(--set <= 0) return true; //finish
223
246
  count = countMax;
224
247
  }
225
248
  tick = tickMax;
226
249
  }
250
+ return false;
227
251
  }
228
252
 
253
+ private static class WorkoutSnapshot implements WorkoutProperties {
254
+ private int tick, tickMax;
255
+ private int count, set;
256
+
257
+ WorkoutSnapshot(Workout wo) {
258
+ this.tick = wo.tick;
259
+ this.tickMax = wo.tickMax;
260
+ this.count = wo.count;
229
- void stop() {
261
+ this.set = wo.set;
262
+ }
263
+
264
+ public int getSet() { return set; }
265
+ public int getCount() { return count; }
266
+ public int getTick() { return tick; }
267
+ public int getTickMax() { return tickMax; }
268
+ public int getLeftSecond() { return calcLeftSecond(tick); }
269
+ }
270
+
271
+ private synchronized void postProgress(WorkoutProperties properties) {
230
- if(countDownTimer != null) {
272
+ if(listener != null) {
231
- countDownTimer.cancel();
273
+ listener.progress(properties);
274
+ }
275
+ }
276
+
277
+ private synchronized void postFinish(WorkoutProperties properties) {
232
- countDownTimer = null;
278
+ if(listener != null) {
233
- listener.stop(this);
279
+ listener.finish(properties);
234
280
  listener = null;
235
281
  }
236
282
  }
237
283
 
284
+ synchronized void stop() {
285
+ if(timer != null) {
238
- void reset() {
286
+ timer.cancel();
287
+ timer = null;
288
+ if(listener != null) {
239
- this.count = countMax;
289
+ listener.stop(this);
240
- this.set = setMax;
290
+ listener = null;
241
- this.tick = tickMax;
291
+ }
292
+ }
242
293
  }
294
+
295
+ synchronized void reset() {
296
+ if(timer == null) {
297
+ this.count = countMax;
298
+ this.set = setMax;
299
+ this.tick = tickMax;
300
+ }
301
+ }
243
302
  }
244
303
  ```

1

Workout のイベント発生とカウントダウンのタイミングを変更

2020/05/13 15:50

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -149,6 +149,7 @@
149
149
  package com.teratail.q259715;
150
150
 
151
151
  import android.os.CountDownTimer;
152
+ import android.util.Log;
152
153
 
153
154
  class Workout {
154
155
  interface Listener {
@@ -158,7 +159,7 @@
158
159
  void stop(Workout workout);
159
160
  }
160
161
 
161
- private static final int PARTICLE_SIZE = 2; //1秒を何tickに分けるか
162
+ private static final int PARTICLE_SIZE = 20; //1秒を何tickに分けるか
162
163
 
163
164
  //private String name;
164
165
  //private int time; //トレーニング時間[s]
@@ -171,6 +172,7 @@
171
172
  private CountDownTimer countDownTimer;
172
173
  private int tick, tickMax;
173
174
  private int count, set;
175
+ private boolean firstTick = false; //CountDownTimer の 最初の onTick を無視するため
174
176
 
175
177
  Workout(String name, int time, int rest_time, int count, int set, int set_during) {
176
178
  //this.name = name;
@@ -189,35 +191,40 @@
189
191
  int getCount() { return count; }
190
192
  int getTick() { return tick; }
191
193
  int getTickMax() { return tickMax; }
192
- int getLeftSecond() { return tick / PARTICLE_SIZE; }
194
+ int getLeftSecond() { return (tick+PARTICLE_SIZE-1) / PARTICLE_SIZE; }
193
195
 
194
196
  void start(Listener listener) {
195
197
  this.listener = listener;
196
198
  long millisInFuture = (tick+tickMax*(count*set-1))*1000L/PARTICLE_SIZE;
199
+ firstTick = true;
197
200
  countDownTimer = new CountDownTimer(millisInFuture, 1000L/PARTICLE_SIZE) { //[ms]
198
201
  @Override
199
- public void onTick(long millisUntilFinished) {
202
+ public void onTick(long ignore) {
200
- tick --;
203
+ if(firstTick) { //最初の onTick を無視
201
- if(tick < 0) {
204
+ firstTick = false;
202
- tick = tickMax - 1;
203
- if(--count <= 0) {
204
- set --;
205
+ return;
205
- count = countMax;
206
- }
207
206
  }
207
+ downTick();
208
208
  Workout.this.listener.progress(Workout.this);
209
209
  }
210
210
  @Override
211
211
  public void onFinish() {
212
- tick = 0;
212
+ onTick(0L); //終了時の Tick を発生(したように見せかける)
213
- count = 0;
214
- set = 0;
215
213
  Workout.this.listener.finish(Workout.this);
216
214
  Workout.this.listener = null;
217
215
  }
218
216
  }.start();
219
217
  listener.start(Workout.this);
220
218
  }
219
+ private void downTick() {
220
+ if(--tick <= 0) {
221
+ if(--count <= 0) {
222
+ if(--set <= 0) return; //finish
223
+ count = countMax;
224
+ }
225
+ tick = tickMax;
226
+ }
227
+ }
221
228
 
222
229
  void stop() {
223
230
  if(countDownTimer != null) {