回答編集履歴
3
rest_counts/rest_sets 及び Status 関係を追加
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,
|
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
|
-
|
182
|
+
private String name;
|
175
|
-
|
183
|
+
private int time; //トレーニング時間[s]
|
176
|
-
|
184
|
+
private int rest_counts; //休憩時間[s]
|
177
185
|
private int countMax; //カウント
|
178
186
|
private int setMax; //セット数
|
179
|
-
|
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
|
205
|
+
Workout(String name, int time, int rest_counts, int count, int set, int rest_sets) {
|
188
|
-
|
206
|
+
this.name = name;
|
189
|
-
|
207
|
+
this.time = time;
|
190
|
-
|
208
|
+
this.rest_counts = rest_counts;
|
191
209
|
this.countMax = count;
|
192
210
|
this.setMax = set;
|
193
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
279
|
+
if(--count <= 0) {
|
280
|
+
if(--set <= 0) {
|
281
|
+
status = Status.Nonexecution;
|
245
|
-
|
282
|
+
return true; //finish
|
246
|
-
count = countMax;
|
247
|
-
|
283
|
+
}
|
284
|
+
}
|
285
|
+
status = Status.RestCounts;
|
286
|
+
tickMax = rest_counts * PARTICLE_SIZE;
|
248
|
-
|
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
|
-
|
339
|
+
count = countMax;
|
298
|
-
|
340
|
+
set = setMax;
|
341
|
+
tickMax = time * PARTICLE_SIZE;
|
299
|
-
|
342
|
+
tick = tickMax;
|
343
|
+
status = Status.Nonexecution;
|
300
344
|
}
|
301
345
|
}
|
302
346
|
}
|
2
CountDownTimer から Timer#scheduleAtFixedRate に変更
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.
|
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,
|
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(
|
88
|
+
private void showWorkout(WorkoutProperties properties) {
|
89
|
-
countTextView.setText(""+
|
89
|
+
countTextView.setText(""+properties.getCount());
|
90
|
-
setTextView.setText(""+
|
90
|
+
setTextView.setText(""+properties.getSet());
|
91
|
-
progressBar.setProgress(workout.getTick());
|
92
91
|
|
92
|
+
progressBar.setProgress(properties.getTickMax() - properties.getTick());
|
93
|
+
|
93
|
-
int left =
|
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(
|
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(
|
117
|
+
public void progress(WorkoutProperties properties) {
|
117
|
-
showWorkout(
|
118
|
+
showWorkout(properties);
|
118
119
|
}
|
119
120
|
|
120
121
|
@Override
|
121
|
-
public void finish(
|
122
|
+
public void finish(WorkoutProperties properties) {
|
122
|
-
showWorkout(
|
123
|
+
showWorkout(properties);
|
123
124
|
startStopButton.setEnabled(false);
|
124
125
|
resetButton.setEnabled(true);
|
125
126
|
}
|
126
127
|
|
127
128
|
@Override
|
128
|
-
public void stop(
|
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.
|
152
|
+
import android.os.Handler;
|
152
|
-
import android.util.Log;
|
153
153
|
|
154
|
+
import java.util.*;
|
155
|
+
|
154
|
-
|
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(
|
166
|
+
void start(WorkoutProperties properties);
|
157
|
-
void progress(
|
167
|
+
void progress(WorkoutProperties properties);
|
158
|
-
void finish(
|
168
|
+
void finish(WorkoutProperties properties);
|
159
|
-
void stop(
|
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
|
182
|
+
private Timer timer;
|
173
183
|
private int tick, tickMax;
|
174
184
|
private int count, set;
|
175
|
-
private
|
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
|
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
|
-
|
213
|
+
timer = new Timer();
|
200
|
-
|
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
|
-
|
219
|
+
@Override
|
202
|
-
|
220
|
+
public void run() {
|
203
|
-
|
221
|
+
boolean finish = downTick();
|
222
|
+
final WorkoutProperties properties = new WorkoutSnapshot(Workout.this);
|
223
|
+
handler.post(new Runnable() {
|
204
|
-
|
224
|
+
public void run() {
|
205
|
-
|
225
|
+
postProgress(properties);
|
206
226
|
}
|
227
|
+
});
|
228
|
+
if(finish) {
|
229
|
+
synchronized(this) {
|
207
|
-
|
230
|
+
timer.cancel();
|
231
|
+
timer = null;
|
232
|
+
}
|
233
|
+
handler.post(new Runnable() {
|
234
|
+
public void run() {
|
208
|
-
|
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
|
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
|
-
|
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(
|
272
|
+
if(listener != null) {
|
231
|
-
|
273
|
+
listener.progress(properties);
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
private synchronized void postFinish(WorkoutProperties properties) {
|
232
|
-
|
278
|
+
if(listener != null) {
|
233
|
-
listener.
|
279
|
+
listener.finish(properties);
|
234
280
|
listener = null;
|
235
281
|
}
|
236
282
|
}
|
237
283
|
|
284
|
+
synchronized void stop() {
|
285
|
+
if(timer != null) {
|
238
|
-
|
286
|
+
timer.cancel();
|
287
|
+
timer = null;
|
288
|
+
if(listener != null) {
|
239
|
-
|
289
|
+
listener.stop(this);
|
240
|
-
|
290
|
+
listener = null;
|
241
|
-
|
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 のイベント発生とカウントダウンのタイミングを変更
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 =
|
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
|
202
|
+
public void onTick(long ignore) {
|
200
|
-
|
203
|
+
if(firstTick) { //最初の onTick を無視
|
201
|
-
|
204
|
+
firstTick = false;
|
202
|
-
tick = tickMax - 1;
|
203
|
-
if(--count <= 0) {
|
204
|
-
|
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
|
-
|
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) {
|