ChatGPTに、Androidアプリでタップした時にテキストを1秒表示して消す処理を聞いて、実際に実行させてみる →そのままで正常動作

#   はじめに

Androidのアプリの作り方を、ほとんど知らない状態で(※1・※2)、タップした時にテキストを1秒表示して消すような、簡単なサンプルアプリを試しに作ってみようと思った時に、

Androidアプリに関わったことがない、何も分からない状態で、一から検索して読み調べてコードを作るのは(簡単なコードであっても)相当面倒くさいな…、と思ってしまいます。

そこで、ChatGPTに聞いて、タップした時にテキストを1秒表示して消す動作を行うサンプルプログラムを作ってもらい、うまく動作するかを試してみます。

※1: ただし、Android Studioの空のサンプルプロジェクトをそのままビルドしてスマホ上で動作させる所までは(最低限)、出来た状態を想定します。
※2: ただし、C#やPythonなどプログラムについては、ある程度知っている状態を想定します。

#   ChatGPTにサンプルプログラムを聞いてみる

現在最新のAndroid 13で動作するように、「Android 13、～」を付けます。
また、Javaのコードとなるように、「Java、～」を付けます。

https://chat.openai.com/

質問中の画面例: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/1b63e52c-a75a-81e3-535b-0ee2814a1572.png)

##   タップした時に別のテキストを1秒表示して消すには？

**▼私(人間)**
Android 13、Java、あるテキストをタップした時に別のテキストを1秒表示して消すには？

**▼ChatGPT(自動応答)**
Androidアプリで、特定のテキストをタップした際に別のテキストを一定時間表示してから消す方法は、いくつかの方法があります。以下に、Javaを使用してこれを実装する例を示します。

まず、レイアウトXMLファイルで、表示するテキストを表示するためのTextViewを配置します。

```xml
<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Tap here"
    android:clickable="true"
    android:onClick="displayText" />
```

次に、Javaファイルで、タップイベントが発生した際に別のTextViewにテキストを表示し、1秒後に消す方法を実装します。

```java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView textViewToDisplay;
    private TextView textViewToTap;

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

        textViewToDisplay = findViewById(R.id.textViewToDisplay);
        textViewToTap = findViewById(R.id.textView1);
    }

    public void displayText(View view) {
        textViewToDisplay.setVisibility(View.VISIBLE);
        textViewToDisplay.setText("Text to display");

        // 1秒後にテキストを非表示にする
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                textViewToDisplay.setVisibility(View.GONE);
            }
        }, 1000);
    }
}
```

このコードでは、textViewToTapというTextViewをタップすると、displayTextメソッドが呼び出されます。displayTextメソッド内では、textViewToDisplayという別のTextViewにテキストを表示し、Handlerを使用して1秒後にそのテキストを非表示にします。

:::note info
上記の自動応答の回答は、質問の意図通りとなる、正しいコードになりました。(ただ、textViewToDisplayに対するxmlの定義がないので、不完全。)
:::

##   どこに書いたらいい？

上記のコードは、どこに書いたら良いのかすら、知識がありません。
Android Studioで、Empty Activityというテンプレートプロジェクトを選択すると、既定の新しい空アプリを作成できるので、この空アプリの中のどこに書いたら良いかを聞いてみます。

**▼私(人間)**
上記のコードは、Android StudioのEmpty Activityテンプレートプロジェクトを基に始める時、どこに書いたらいい？

**▼ChatGPT(自動応答)**
Android StudioのEmpty Activityテンプレートプロジェクトを使用して始める場合、上記のコードを書く場所は次の通りです。

1. XMLレイアウトファイル: `res/layout/activity_main.xml`
   ここには、TextViewを配置してタップイベントを処理するための属性も含まれます。

2. Javaファイル: `MainActivity.java`
   ここには、タップイベントを処理するJavaコードが含まれます。

以下に、各ファイルにコードを追加する手順を示します。

1. activity_main.xmlには、次のようにTextViewを配置します。

```xml
<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Tap here"
    android:clickable="true"
    android:onClick="displayText" />

<TextView
    android:id="@+id/textViewToDisplay"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="gone"
    android:text="Text to display" />
```

2. MainActivity.javaファイルには、次のようなコードを追加します。

```java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView textViewToDisplay;
    private TextView textViewToTap;

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

        textViewToDisplay = findViewById(R.id.textViewToDisplay);
        textViewToTap = findViewById(R.id.textView1);
    }

    public void displayText(View view) {
        textViewToDisplay.setVisibility(View.VISIBLE);
        textViewToDisplay.setText("Text to display");

        // 1秒後にテキストを非表示にする
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                textViewToDisplay.setVisibility(View.GONE);
            }
        }, 1000);
    }
}
```

このように、XMLレイアウトファイルとJavaファイルのそれぞれにコードを追加して、Android StudioのEmpty Activityテンプレートプロジェクトに機能を追加できます。

:::note info
上記の自動応答の回答は、質問の意図通りとなる、正しいコードになりました。(textViewToDisplayのxml定義が自動で追加されて、OK)
:::

##   動作に必要な全体のコード例を記載すると？

**▼私(人間)**
上記のコードを基に、動作に必要な全体のコード例を記載すると？

**▼ChatGPT(自動応答)**
以下に、全体のコード例を示します。このコードは、Android StudioのEmpty Activityテンプレートプロジェクトに追加して動作させることができます。

1. activity_main.xml:

```xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tap here"
        android:layout_centerInParent="true"
        android:clickable="true"
        android:onClick="displayText" />

    <TextView
        android:id="@+id/textViewToDisplay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:text="Text to display"
        android:layout_below="@id/textView1"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>
```

2. MainActivity.java:

```java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView textViewToDisplay;
    private TextView textViewToTap;

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

        textViewToDisplay = findViewById(R.id.textViewToDisplay);
        textViewToTap = findViewById(R.id.textView1);
    }

    public void displayText(View view) {
        textViewToDisplay.setVisibility(View.VISIBLE);
        textViewToDisplay.setText("Text to display");

        // 1秒後にテキストを非表示にする
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                textViewToDisplay.setVisibility(View.GONE);
            }
        }, 1000);
    }
}
```

このコードは、特定のTextViewをタップすると、別のTextViewにテキストが表示され、1秒後に非表示になる動作を実現します。

:::note info
上記の自動応答の回答は、質問の意図通りとなる、正しいコードになりました。(activity_main.xmlは「?xml ～」「RelativeLayout ～」タグが自動で追加されて不足なしOK、MainActivity.javaは先頭にパッケージの定義「package ～」がないものの、その他はOK)
:::

##   実際に実行させてみる→期待通りの動作OK

上記の自動応答で得られたコードは、(上記の指摘通りに、activity_main.xmlとMainActivity.javaファイルに同内容を書いて)、実際に実行してみると、修正の必要なく動作するものになっており、非常に優秀。ほしかった機能を実現するコードが得られました。

画面: 
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/6f024ca4-9a45-82bd-8846-5c51a0947cce.png">
↓タップ後
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/1e53d5cf-a3db-0e36-6b43-31d879ac09b8.png">

##   タップ開始時に表示するように変更

:::note info
更に高度な要求をしてみます。
:::

上記のコードは、実際にスマホ上で動作させると初めて気付きますが、クリック＝タップを離してから表示されて1秒後に消える動作になっています。これを、タップ開始時から表示するように変更できるか、聞いてみます。

**▼私(人間)**
上記のコードで、タップ開始時に表示するように変更

**▼ChatGPT(自動応答)**
理解しました。以下に、タップ開始時にテキストを表示し、1秒後に非表示にするように変更したコードを示します。

```xml
<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tap here"
        android:layout_centerInParent="true"
        android:clickable="true"
        android:onClick="displayText" />

    <TextView
        android:id="@+id/textViewToDisplay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:text="Text to display"
        android:layout_below="@id/textView1"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>
```

```java
// MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView textViewToDisplay;
    private TextView textViewToTap;

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

        textViewToDisplay = findViewById(R.id.textViewToDisplay);
        textViewToTap = findViewById(R.id.textView1);
    }

    public void displayText(View view) {
        textViewToDisplay.setVisibility(View.VISIBLE);
        textViewToDisplay.setText("Text to display");

        // 1秒後にテキストを非表示にする
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                textViewToDisplay.setVisibility(View.GONE);
            }
        }, 1000);
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            displayText(null);
        }
        return super.onTouchEvent(event);
    }
}
```

上記の変更では、タッチイベントが発生したときに直接 `displayText` メソッドを呼び出すように変更されました。そのため、`displayText` メソッドを直接呼び出す必要がなくなりました。

:::note info
上記の自動応答の回答は、onClickイベントとonTouchEventイベントの両方でdisplayText(表示→1秒後に非表示にする処理)が呼ばれて、動作がおかしくなる可能性があります。より詳しく質問を記載して聞き直してみます。
:::

**▼私(人間)**
上記のコードは、onClickイベントとonTouchEventイベントの両方でdisplayTextが呼ばれて、動作がおかしくなる可能性あり。
タップ開始時に表示して、タップ終了から1秒後に非表示にするように変更するには？

**▼ChatGPT(自動応答)**
申し訳ありません、誤解がありました。以下のようにコードを変更して、タップ開始時に表示して、タップ終了から1秒後に非表示にするように修正します。

```java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView textViewToDisplay;

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

        textViewToDisplay = findViewById(R.id.textViewToDisplay);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            displayText();
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            // 1秒後にテキストを非表示にする
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    textViewToDisplay.setVisibility(View.GONE);
                }
            }, 1000);
        }
        return super.onTouchEvent(event);
    }

    private void displayText() {
        textViewToDisplay.setVisibility(View.VISIBLE);
        textViewToDisplay.setText("Text to display");
    }
}
```

このコードでは、タッチダウンイベント（タップ開始時）で `displayText()` メソッドが呼び出され、テキストが表示されます。そして、タッチアップイベント（タップ終了時）で1秒後にテキストを非表示にするように設定されています。

:::note info
上記の自動応答の回答は、タップ終了時から1秒後に非表示にする動作になっており、質問の意図通りとなる、正しいコードになりました。
:::

**▼私(人間)**
displayText()関数に分けなくていいのでは？
activity_main.xmlには変更なしでOK？

**▼ChatGPT(自動応答)**
ご指摘の通りです。`displayText()` 関数を分ける必要はありません。また、`activity_main.xml` には変更は必要ありません。

以下に、`displayText()` 関数を分けずに修正したコードを示します。

```java
// MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView textViewToDisplay;
    private TextView textViewToTap;

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

        textViewToDisplay = findViewById(R.id.textViewToDisplay);
        textViewToTap = findViewById(R.id.textView1);

        textViewToTap.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    textViewToDisplay.setVisibility(View.VISIBLE);
                    textViewToDisplay.setText("Text to display");
                } else if (event.getAction() == MotionEvent.ACTION_UP) {
                    Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            textViewToDisplay.setVisibility(View.GONE);
                        }
                    }, 1000);
                }
                return true;
            }
        });
    }
}
```

この修正により、`displayText()` 関数を分けることなく、タップ開始時にテキストを表示し、タップ終了後に1秒後にテキストを非表示にします。

:::note info
上記の自動応答の回答は、質問の意図通りとなる、正しいコードになりました。(ただ、前回のactivity_main.xmlの内容から「android:onClick="displayText"」イベントの登録はしないように削除の変更が必要となるはず。)
:::

##   実際に実行させてみる→期待通りの動作OK

上記の自動応答で得られたコードは、実際に実行してみると、修正の必要なく、完全に期待通りの動作をするものになっており、非常に優秀。ほしかった機能を実現するコードが得られました。

##   連続でタップすると1秒も経たずに非表示となる問題

:::note info
更に高度な要求をしてみます。
:::

上記のコードは、実際にスマホ上で動作させると初めて気付きますが、連続でタップすると1秒も経たずに非表示となることがあり、これを修正できるか、聞いてみます。

**▼私(人間)**
上記のコードで、連続でタップすると1秒も経たずに非表示となる問題があり、これを修正するには？

**▼ChatGPT(自動応答)**
連続してタップされた場合、新しい非表示のタイマーが設定される前に以前の非表示のタイマーがリセットされる必要があります。これを実現するには、Handlerによって投稿された以前の非表示のタスクをキャンセルする必要があります。

以下は、修正されたコードです。

```java
// MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView textViewToDisplay;
    private TextView textViewToTap;
    private Handler handler;
    private Runnable hideTextRunnable;

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

        textViewToDisplay = findViewById(R.id.textViewToDisplay);
        textViewToTap = findViewById(R.id.textView1);
        
        handler = new Handler();
        hideTextRunnable = new Runnable() {
            @Override
            public void run() {
                textViewToDisplay.setVisibility(View.GONE);
            }
        };

        textViewToTap.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    textViewToDisplay.setVisibility(View.VISIBLE);
                    textViewToDisplay.setText("Text to display");
                } else if (event.getAction() == MotionEvent.ACTION_UP) {
                    // 既存の非表示タスクをキャンセル
                    handler.removeCallbacks(hideTextRunnable);
                    // 新しい非表示タスクを投稿
                    handler.postDelayed(hideTextRunnable, 1000);
                }
                return true;
            }
        });
    }
}
```

この修正により、連続してタップされた場合でも、以前の非表示のタイマーがリセットされます。

:::note info
上記の自動応答の回答は、質問の意図通りとなる、正しいコードになりました。(連続でタップしても1秒後に非表示となり、すばらしい修正。)
:::

##   実際に実行させてみる→期待通りの動作OK

上記の自動応答で得られたコードは、実際に実行してみると、修正の必要なく、完全に期待通りの動作をするものになっており、非常に優秀。ほしかった機能を実現するコードが得られました。


#   まとめ

本稿で設定したタスク(Androidアプリでタップした時にテキストを1秒表示して消す処理)に対して、ChatGPTが生成したコードは、実際に実行してみると、修正の必要なく、完全に期待通りの動作をするものになっており、非常に優秀なことが分かります。**ほしかった機能を実現するコードが日本語を書いただけで簡単に得られました**。

途中で付け加えた、**高度な要求(タップ開始時から1秒表示する変更・連続でタップした時の問題)にも、最終的には期待通りの正しいコードが生成されて**、大変すばらしい結果となりました。

一般的によくある機能・内容であれば、ほとんど正しいコード例が得られて、そのままエラーなく実行可能ということが分かります。
Androidアプリに関わったことがない場合など、**ほとんど知らない状態で、ほしい機能を実現するコードが欲しい(けれど検索して調べてコード作って…が面倒な)時**に、**ほしいものを聞くだけでコードが得られる**、とても便利なツールであることが分かります。

以前、下記の記事で、ChatGPTにメジャーではない処理のコードを聞いてみると、生成されたコードが全く意図と違って全然使えなかった結果を記載しましたが、本稿のような一般的によくある機能であれば、ほとんど正しいコード例が得られて、とても便利なことが分かります。

https://qiita.com/dl_from_scratch/items/fec09443ca0c1d6ea8fa


#   参考

##   ChatGPTの始め方

記事: 【無料】チャットGPTの始め方を解説！

https://www.minotake-gadget.net/chatgpt-howto/

##   バージョン

ChatGPT 3.5