ドロでタイマーアプリの作成

## **かんたん色々な機能?を持つタイマー**

2019年12月10日に書かないといけなかったのですが年を越してしまいました。

では、今回紹介しますは↓

_「タイマー」アプリ！！！_

スタート、ストップ、リセット以外に簡単な機能（すごくいらない機能）を付け加えて見ました。


画像完成イメージです。↓
![Photo_20-01-08-16-38-02.318.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214221/0abb18f0-c4f1-71af-9bc6-5f7b52bcd5de.png)


# **_必要なもの_**

・PC

・Android Studio (主は3.0.1)

# **_アプリ作成-1 準備_**

いつもどおりに、プロジェクトを作成していきます。

・APIレベルは26（android8.0）で作ってます。

・Activityの種類はEmptyを指定してます。

# **_アプリ作成-2 画面作り_**

画面にボタンを配置していきましょう。

activity_main.xml

``````xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
〜省略〜
>


    <TextView
        android:id="@+id/text_view_countdown"
        android:layout_width="395dp"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_marginEnd="7dp"
        android:layout_marginStart="7dp"
        android:gravity="center"
        android:text="@string/_00_00"
        android:textColor="@android:color/black"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.48"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.280" />

    <Button
        android:id="@+id/button_start_pause"
        android:layout_width="395dp"
        android:layout_height="43dp"
        android:layout_below="@+id/text_view_countdown"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:text="@string/start"
        app:layout_constraintBottom_toTopOf="@+id/button_reset"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_view_countdown" />

    <Button
        android:id="@+id/button_reset"
        android:layout_width="395dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_start_pause"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="8dp"
        android:text="@string/reset"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_start_pause"
        tools:visibility="visible" />
    <Button
        android:id="@+id/button_pause"
        android:layout_width="395dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_reset"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="8dp"
        android:text="@string/pause"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_reset"
        tools:visibility="visible" />

    <Button
        android:id="@+id/button_skip"
        android:layout_width="395dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_pause"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="8dp"
        android:text="@string/skip"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_pause"
        tools:visibility="visible" />

    <Button
        android:id="@+id/button_return"
        android:layout_width="395dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_skip"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="8dp"
        android:text="@string/not_return"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_skip"
        tools:visibility="visible" />

</android.support.constraint.ConstraintLayout>

``````

はいViewでございます。（android.support.constraint.ConstraintLayoutはそれぞれ個人により異なります。）

``````xml
        android:text="@string/pause"
``````
とかでエラーを起こされると思いますので、今度はstrings.xmlを追記していきます。

``````xml
<resources>
    <string name="app_name">timer</string>
    <string name="_00_00">00:00</string>
    <string name="start">スタート</string>
    <string name="reset">リセット</string>
    <string name="stop">STOP</string>
    <string name="pause">ザ・ワールド</string>
    <string name="skip">キング・クリムゾン</string>
    <string name="not_return">GER</string>
</resources>
``````

はい、pause、skipボタンの名前は各自適当にあてましょう

これで画面は表示できる状態になるかとおもいます。

# **_アプリ作成-3 タイマーの処理1_**

MainActivity.javaに画面にあるそれぞれのボタンを押下時の処理を書いていきます！！

が

最初にフィールド変数を定義します。

``````java
public class MainActivity extends AppCompatActivity {

    //タイマー設定 単位 ミリ秒
    private static final long START_TIME_IN_MILLIS = 180000;

    //一時停止設定 単位 ミリ秒
    private static final long PAUSE_IN_MILLIS = 7000;

    //スキップ設定 単位 ミリ秒
    private static final long SKIP_TIME_IN_MILLIS = 5000;

    //カウントダウンタイマー
    private TextView mTextCountDown;
    //ボタン
    private Button mButtonStart;    //スタート
    private Button mButtonReset;    //リセット
    private Button mButtonPause;    //一時停止
    private Button mButtonSkip;     //スキップ
    private Button mButtonReturn;   //戻る

    //CountDownTimerクラス
    private CountDownTimer mCountDownTimer;
    //CallTimeクラス
    private boolean mTimerRunning;

    private long mTime = START_TIME_IN_MILLIS;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    〜省略〜
``````

ここでタイマーの初期時間、一時停止の停止時間、スキップの飛ばす時間を定義します。

# **_アプリ作成-3 タイマーの処理2_**

それぞれのボタン押下時の挙動を先に書きます！

``````java
//〜上にprotected void onCreate(Bundle savedInstanceState)のあれがあります。〜

    //タイマー再開の処理
    private void startTimer() {
        mCountDownTimer = new CountDownTimer(mTime,1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                mTime = millisUntilFinished;
                updateCountDownText();
            }

            @Override
            public void onFinish() {
                mTimerRunning = false;  //タイマー停止中
                mTime = START_TIME_IN_MILLIS;
                mButtonStart.setText("スタート");
                mButtonReset.setVisibility(View.INVISIBLE);
                mButtonPause.setVisibility(View.INVISIBLE);
                mButtonSkip.setVisibility(View.INVISIBLE);
                mButtonReturn.setVisibility(View.INVISIBLE);
            }
        }.start();

        mTimerRunning = true;   //タイマー作動中
        mButtonStart.setText("一時停止");
        mButtonReset.setVisibility(View.VISIBLE);
        mButtonPause.setVisibility(View.VISIBLE);
        mButtonSkip.setVisibility(View.VISIBLE);
        mButtonReturn.setVisibility(View.VISIBLE);

    }

    //タイマー一時停止の処理
    private void pauseTimer() {
        mCountDownTimer.cancel();
        mTimerRunning = false;
        mButtonStart.setText("スタート");
        mButtonReset.setVisibility(View.VISIBLE);
    }

    //タイマーリセットの処理
    private void resetTimer() {
        mTime = START_TIME_IN_MILLIS;
        updateCountDownText();
        mCountDownTimer.cancel();
        mButtonStart.setText("スタート");
        mTimerRunning = false;
        mButtonStart.setVisibility(View.VISIBLE);
        mButtonReset.setVisibility(View.INVISIBLE);
        mButtonPause.setVisibility(View.INVISIBLE);
        mButtonSkip.setVisibility(View.INVISIBLE);
        mButtonReturn.setVisibility(View.INVISIBLE);

    }

    //タイマー表示
    private void updateCountDownText() {
        int minutes = (int)(mTime / 1000) / 60;
        int seconds = (int)(mTime / 1000) % 60;

        String timeFormatted = String.format(Locale.getDefault(), "%02d:%02d",minutes,seconds);
        mTextCountDown.setText(timeFormatted);
    }
``````

これでボタンの押したときにそれぞれ動く処理を書きました。

基本的には「タイマーを止める」を応用したやり方でスキップや停止を実現している感じです。

# **_アプリ作成-3 タイマーの処理3_**

ボタンにonClickを実装して押下したときに動くようにします

``````java
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextCountDown  = findViewById(R.id.text_view_countdown);
        mButtonStart    = findViewById(R.id.button_start_pause);
        mButtonReset    = findViewById(R.id.button_reset);
        mButtonPause    = findViewById(R.id.button_pause);
        mButtonSkip     = findViewById(R.id.button_skip);
        mButtonReturn   = findViewById(R.id.button_return);

        //スタートボタン
        mButtonStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //タイマーの状態を取得
                if (mTimerRunning) {
                    //動いてるなら停止
                    pauseTimer();
                } else {
                    startTimer();
                }
            }
        });

        //リセットボタン
        mButtonReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //タイマーのリセット
                resetTimer();
            }
        });

        //一時停止ボタン
        mButtonPause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //タイマーを停止
                mCountDownTimer.cancel();
                //7秒後実行
                new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //タイマーの再開
                        startTimer();
                    }
                }, PAUSE_IN_MILLIS);

            }
        });

        //スキップボタン
        mButtonSkip.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //タイマーを停止
                mCountDownTimer.cancel();
                int futureTime = (int)(mTime - SKIP_TIME_IN_MILLIS);
                //残り時間が0以上あるならスキップ
                if (futureTime >= 0) {
                    mTime = futureTime;
                    int minutes = (futureTime / 1000) / 60;
                    int seconds = (futureTime / 1000) % 60;
                    String timeFormatted = String.format(Locale.getDefault(), "%02d:%02d",minutes,seconds);
                    mTextCountDown.setText(timeFormatted);
                //残り時間0になるならリセット
                } else {
                    resetTimer();
                }
                startTimer();
            }
        });

        //戻るボタン
        mButtonReturn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resetTimer();
                startTimer();

            }
        });

        updateCountDownText();
    }
``````

ここまで書けば、タイマーとして動かせます。
実際にコンパイルして実機で動かしてみてください。

![Photo_20-01-08-16-38-00.994.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214221/912c065a-ddcd-999c-a451-59f4286f2714.png)

****


# **_あとがき_**

読んでいただきありがとうございます。

ほとんどソースのベタ貼りですが、CountDownTimerの使っただけですのであんまり書くことがなかったです。


（他にも色々つけたかったのですが、時間のご都合上ここまでにさせていただきます。ほぼ１ヶ月も期限超えてますしおすし）


最初はカウンターアプリにしようかと思ってました。（ボタン押すたびにカウントアップしてアニメーションで上から下にデュランダルがぶっ刺さる風のやつ）

To Be Continued