【Kotlin研修4日目】コンテキストメニューの実装

# コンテキストメニュー
`ListView`などを長押しした際に表示される小さなポップアップメニュー。

## コンテキストメニューの実装
[参考: 研修4日目](https://qiita.com/b150005/items/1f58b3418bb1690c2f4b)
`コンテキストメニュー`を実装する手順は、以下の通り。

> 1. `res`フォルダ内に、`Resource Type: menu`の`Android Resource Directory`を作成
> 2. 1.で作成したフォルダ内に、`Menu Resource File`(`.xml`ファイル)を作成
> 3. `アクティビティ`クラスに、`コンテキストメニュー`を生成するための<br>`onCreateContextMenu()`メソッドを実装
> 4. `アクティビティ`クラスの`onCreate()`メソッド内に、生成した`コンテキストメニュー`を表示するための<br>`registerForContextMenu()`メソッドを記述
> 5. `コンテキストメニュー`の`Item`選択時に呼び出される`onContextItemSelected()`メソッドに、<br>選択された`コンテキストメニューItem`に応じた分岐処理を記述

### Menu Resource Fileの記述
`コンテキストメニュー`の`Item`含む`レイアウト`を定義する`XML`ファイル。

#### Menu Resource File
[参考: メニューリソース](https://developer.android.com/guide/topics/resources/menu-resource?hl=ja)
`アプリ`内に実装する各種`メニュー`のレイアウトを定義する`XML`ファイル。
`メニュー`には、`コンテキストメニュー`のほか、[`オプションメニュー`](https://qiita.com/b150005/items/1f58b3418bb1690c2f4b)、[`サブメニュー`]()が含まれる。

#### 定義

```xml
<?xml version="1.0" encoding="utf-8"?>
<menu
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/<ItemID>"
        android:title="@string/<strings.xmlで定義した文字列の変数名>"
    />
</menu>
```

### コンテキストメニューの生成
[参考: ContextMenu](https://developer.android.com/reference/kotlin/android/view/ContextMenu)
`コンテキストメニュー`の**表示時**に呼び出される`onCreateContextMenu()`メソッドのブロック`{...}`内に、
`コンテキストメニュー`の`Item`を定義した`XML`を表示する`MenuInflater.inflate()`メソッドを記述する。
また、`コンテキストメニュー`に`ヘッダタイトル`を表示させる場合は`ContextMenu.setHeaderTitle()`メソッドを記述する。

#### 定義

```kotlin
MenuInflater.inflate(menuRes: Int, menu: Menu!): Unit
// パラメータ
// menuRes: メニューのレイアウトファイル名(R値)
// menu: インフレートを行うメニュー

ContextMenu?.setHeaderTitle(titleRes: Int)
// パラメータ
// titleRes: ヘッダタイトルの文字列ID(R値)
```

#### サンプルコード

```kotlin:MainActivity.kt
class MainActivity: AppCompatActivity() {
    // コンテキストメニュー表示時に呼び出される処理
    override fun onCreateContextMenu(
        menu: ContextMenu?, 
        view: View?, 
        menuInfo: ContextMenu.ContextMenuInfo?
    ) {
        super.onCreateContextMenu(menu, view, menuInfo)

        // コンテキストメニューのレイアウト(XML)のインフレート
        menuInflater.inflate(menuRes: Int, menu: Menu!): Unit

        // ヘッダタイトルの定義
        menu?.setHeaderTitle(titleRes: Int)
    }
}
```

### ListViewへのコンテキストメニューの登録

#### 定義

```kotlin
Activity.registerForContextMenu(view: View!): Unit
// パラメータ
// view: コンテキストメニューを表示するビュー
```

#### サンプルコード

```kotlin:MainActivity.kt
class MainActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        val lvMenu = findViewById<ListView>(R.id.lvMenu)
        ...
        // 生成したコンテキストメニューを指定したビュー(ListView)に登録
        registerForContextMenu(lvMenu)
    }
}
```

### コンテキストメニューのItem選択時の処理
[参考: 研修2日目](https://qiita.com/b150005/items/f20cfec328d1029fd4b8)
`コンテキストメニュー`も`オプションメニュー`と同様、`アイテム`が既定で`リスナ`として定義されているため、<br>`アイテム`**選択時**に呼び出される`onContextItemSelected()`メソッドを用いて、<br>選択された`アイテム`に応じた分岐処理(`イベントハンドラ`)を実装する。
※`アイテム`が選択されない場合は、`super.onContextItemSelected()`の返り値(=`false`)を返却する必要がある。

#### サンプルコード

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    // コンテキストメニューItemの"タップ"イベント検知時の処理(イベントハンドラ)
    // onContextItemSelected(item:): オプションメニューのItemがタップされた場合に呼び出されるメソッド
    // item: タップされたItem
    override fun onContextItemSelected(item: MenuItem): Boolean {
        // 最終的に返却するBool値(初期値: true)
        var returnVal = true

        // AdapterContextMenuInfoオブジェクトの定義
        // -> コンテキストメニューを呼び出したItemの情報を格納
        val info = item.menuInfo as AdapterView.AdapterContextMenuInfo

        // コンテキストメニューを呼び出したItemのIndex番号
        val listPosition = info.position

        // コンテキストメニューを呼び出したItemのキーと値を格納するMutableList
        val menu = _menuList[listPosition]

        // タップされたItemに応じた分岐処理
        // MenuItem.itemId: ItemのID(R値)
        when(item.itemId) {
            R.id.menuListContextDesc -> {
                // トースト表示する文字列
                val desc = menu["desc"] as String
                
                // 表示するトーストの定義
                val toast = Toast.makeText(this@MainActivity, desc, Toast.LENGTH_LONG)
                
                // トーストの表示
                toast.show()
            }

            R.id.menuListContextOrder ->
                ...

            else ->
                // オプションメニューのItem以外が選択された場合は、
                // 親クラス(super)のonContextItemSelected(item:)メソッドの
                // 返り値(デフォルトではfalse)を返却
                returnVal = super.onContextItemSelected(item)
        }

        return returnVal
    }
}
```