【Android-Codelabs】6/36 〜 EditTextを使って入出力のできるアプリの作り方 〜


2019年にGoogleから，Web上でAndroidを学べるコースが提供されました．([Android Kotlin Fundamentals Course](https://codelabs.developers.google.com/android-kotlin-fundamentals/))
この記事では，そのコースを実際にやってみてアウトプットしてみるといった内容です．
何かツッコミなどあれば編集リクエストかコメントかTwitterでいただければ修正いたします :pray:

#今回学ぶこと
・`EditText`のビューを使用して，ユーザー入力を取得する方法
・`visibilty`属性を使って，Viewの可視性（Visible）を変更する方法

#目指す成果物

ここでは，前回使ったアプリにインタラクティブ機能を追加します．ソースコードは[こちら](https://github.com/syuheifujita/android-codeLab-fundamental-2-1)になります．

![2-2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/b947ba10-0ba8-12b7-1e5c-de82c448af3c.png)
![2-2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/c36eff50-ca17-72cf-5f73-19bedfaeaf07.png)


ユーザーはニックネームを入力し，DONEボタンをタップすると，`TextView`は入力されたニックネームを表示されます．
また，`TextView`をタップするとニックネームを再度更新されます．

#ステップ
###1. テキスト入力用のEditTextを追加する

ここでは，`EditText`ビューを追加して，ユーザーがニックネームを追加できるようにします．

`EditText`は`TextView`のサブクラスです．
このように，ユーザーはテキストを入力して，テキストの入力や編集ができます．

![2-2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/2fea77aa-82f6-ba1e-8650-6ae1c64fa1a5.png)


まず，レイアウトファイル`activity_main.xml`で，`name_text`の下に`EditText`を定義しましょう．

![2-2-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/de33b2e7-c326-8b47-cd79-8414dad3ef1d.png)


```activity_main.xml
<EditText
    android:id="@+id/nickname_edit"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/what_is_your_nickname"
    android:layout_margin="16dp"/>
```

hint属性は，入力する前に薄いもじが表示されているようなデザインにすることができます．(テキストはstring.xmlで設定)

そしたらアプリを実行してみましょう．
スターの画像の上に，hint属性の「Name」を含む`EditText`が表示されます

![2-2-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/157ca855-fe2f-7d60-19fd-7f408e58842c.png)


###2. EditTextのスタイルを設定する

ここでは，スタイルを`NameStyle`に変更，`inputType`属性を設定することにより`EditText`のビューのスタイルを設定していきます．

まず，スタイルはstyle属性で指定していきます．
`style="@style/NAmeStyle”`を追加します．

次に，`inputType`属性は，ユーザーが`EditText`ビューに入力できる入力のタイプを指定します．

たとえば，パスワードの場合，`textPassword`を使います．
![2-2-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/1c36fe75-59bc-9f7a-9a20-81c02de9c724.png)


電話番号には，`phone`を使います．数字キーパッドが表示され，ユーザは数字のみを入力できます．
![2-2-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/3b3d4809-9793-0f64-354d-df6f6438bb18.png)


そして`EditText`の属性はこのようにします．

```activity_main.xml
<EditText
    android:id="@+id/nickname_edit"
    style="@style/NameStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="8dp"
    android:hint="@string/what_is_your_nickname"
    android:inputType="textPersonName" />
```

###3. ボタンを追加する

`Button`は，ユーザーがタップのアクションを実装できるUI要素です．
テキスト，アイコン，テキストとアイコンの両方でも実装できます．

![2-2-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/dad6ac6d-06c0-1f43-0fdb-f5f4e65e3eb3.png)



まず，Doneボタンを追加します．
`Button`ビューの属性はこのようになります．

```
<Button
    android:id="@+id/done_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/done"
    android:layout_gravity="center_horizontal"/>
```

次に，ボタンの色をアクセントカラーに変更します．
アクセントカラーは`res/values/colors.xml`ファイルで定義されています．

style属性を`Button`ビューに追加しましょう

```
style="@style/Widget.AppCompat.Button.Colored"
```

![2-2-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/e05ae6e4-da98-defc-f999-85742d8394b3.png)


色が変化しましたね！

`color.xml`の属性を変更するとボタンの色も変更できます．

```
<color name="colorAccent">#76bf5e</color>
```

![2-2-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/52df1398-8efc-4191-813f-e589b20674bb.png)


###4. ニックネームを表示するTextViewを追加する

ここでは，色付きの背景を持つTextViewを追加します．

まず，`TextView`を`Button`ビューの下に追加します．
属性はこのようにします．

```activity_main.xml
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/nickname_text"
    android:layout_gravity="center"
    style="@style/NameStyle"/>
```

次に，`TextView`の可視性（Visible）を変更します．
visibility属性を使って，ビューを表示か非表示にすることができます．

また，visibilityには３種類の値があります
・visible：ビューが表示されます
・Invisible：ビューを非表示にしますが、ビューはまだレイアウトのスペースを占有します
・gone：ビューを非表示にし、ビューがレイアウトのスペースを占有しないようにします

`nickname_text`は，最初は表示させたくないので，属性は`android:visibility="gone”`を使います．
レイアウトファイルはこのようにします．

```activity_main.xml
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/nickname_text"
    android:layout_gravity="center"
    style="@style/NameStyle"
    android:visibility="gone"/>
```

###5. ButtonにClickListenerを実装する

ここでは`Button`がタップされた時に，実行される処理を実装していきます．

まず，javaフォルダーから`MainActivity.kt`を開いて，`addNickname`という関数を追加します．
ボタンをタップすると，テキストビューを表示されるので，パラメーターに`view`を指定します．

```MainActivity.kt
package com.example.android_codelab_2_1

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.EditText
import android.widget.TextView

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    private fun addNickname(view: View) {
    }
}
```

次に，ボタンが押された時に`nickname_edit`と`nickname_text`のビューを参照したいので，`addNickname`関数内で`findViewById`を追加します．

```
private fun addNickname(view: View) {
    val editText = findViewById<EditText>(R.id.nickname_edit)
    val nicknameTextView = findViewById<TextView>(R.id.nickname_text)
}
```

そして，`EditText`で入力された値を`TextView`の`text`属性に渡したいので，`nicknameTextView.text = editText.text`要素を追加します．

```
private fun addNickname(view: View) {
    val editText = findViewById<EditText>(R.id.nickname_edit)
    val nicknameTextView = findViewById<TextView>(R.id.nickname_text)

    nicknameTextView.text = editText.text
}
```

値を渡したら，`nickname_edit`は非表示にさせたいので，`visibility`属性を使います．
また同じく，`nickname_text`は表示させたいので，`visibility`属性を使います．

```
private fun addNickname(view: View) {
    val editText = findViewById<EditText>(R.id.nickname_edit)
    val nicknameTextView = findViewById<TextView>(R.id.nickname_text)

    nicknameTextView.text = editText.text

    editText.visibility = View.GONE
    nicknameTextView.visibility = View.VISIBLE
}
```

次に，クリックリスナーを追加します．

`MainActivity.kt`の，`onCreate`メソッド内でこのように定義します．

```
val buttonDone = findViewById<Button>(R.id.done_button)

buttonDone.setOnClickListener {
    addNickname(it)
}
```

`Button`ビューを使いたいので，`findViewById`メソッドを呼び出します．
addNickname()メソッドの`it`は，引数として渡される`done_button`のButtonビューを指しています．

アプリを実行して，ニックネームを入力してDONEボタンをタップしたらこのようになることを確認しましょう．

![2-2-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/529ea595-b4cc-1ad6-9b52-69af9f9a1860.png)
![2-2-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/698070cb-48ad-192b-abb7-934616fd8ce7.png)

次に，ボタンをタップした後にキーボードを隠したいので，このようなコードを`addNickname`関数の最後に追加します．

```
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
```

###6. ニックネームを更新する機能を実装する

ここでは，ニックネームを更新する機能を実装します．
更新するには，`nickname_text`をタップすると，`nickname_edit`と`done_button`を再び表示させるようにします．

まず，更新するために，`updateNickname`関数を定義します．

```
private fun updateNickname (view: View) {
}
```

`nickname_text`をタップすると，`nickname_edit`と`done_button`を再び表示させたいので，関数をこのようにします．

```
private fun updateNickname (view: View) {
    val editText = findViewById<EditText>(R.id.nickname_edit)
    val doneButton = findViewById<Button>(R.id.done_button)

    editText.visibility = View.VISIBLE
    doneButton.visibility = View.VISIBLE
    view.visibility = View.GONE
}
```

次に，MainActivity.ktでリスナーを定義します．

```
nicknameTextView.setOnClickListener() {
    updateNickname(it)
}
```

###7. EditTextにフォーカスを設定して，ユーザビリティを高める

仮に，`nickname_text`をタップして，再び`nickname_edit`が表示されたとしても，編集可能なのかどうかはユーザーに伝わりにくい時があります．
こういった時には，`requestFocus()`関数を使います．

まず，EditTextビューに，`requestFocus()`関数をupdateNickname関数の最後の行に記述して，フォーカスを設定します．

```
editText.requestFocus()
```

次に，キーボードを表示させる，コードをupdateNickname関数の最後の行に記述します．

```
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(editText, 0)
```

以上で終わりになります．

インタラクティブなアプリを作れました！

#まとめ
・EditTextは，ユーザーがテキストの入力や変更ができるUI要素
・visibilty属性で，ビューの表示や非表示を設定できる

#クイズ
>1問目
EditTextはどのサブクラスですか？

View
LinearLayout
TextView
Button

>2問目
visibilityビューに設定されている場合、次の属性のどれがビューを非表示にしてレイアウトのスペースを占有しないようにしますか？

visible
Invisible
gone
hide

>3問目
次の文のうち、Buttonビューについて正しいものはどれですか？

Buttonは、ViewGroupです
Button画面ごとに3つしか配置できません
Buttonはクリック可能であり、クリックすると、クリックリスナーがアクションを実行します
ImageViewはButtonの拡張です

#参考資料
###ソースコード
Github:
https://github.com/syuheifujita/android-codeLab-fundamental-2-2

###言葉の定義
・可視性（Visible）
ビューの表示や非表示を設定できる属性のこと

・アクセントカラー
基本の色に加えて，目立たせるための色としてcolor.xmlにデフォルトで定義されているもののこと

・サブクラス
親クラスを継承した子クラスのこと

・リスナー（Listener）
タップされたかを，見張っておく機能のようなもののこと
ex)onClickListener

###CodeLabs by Google
https://codelabs.developers.google.com/android-kotlin-fundamentals/
![スクリーンショット 2020-02-05 4.07.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/3ad2d3c9-d57f-1b4b-85cf-1c92a57b464b.png)