【Kotlin】ListViewダイアログ 変更可能なリスト②

#■ダイアログ
アクション時にログが表示される。


#■準備

■stling.xml
文字準備

``` kotlin
<resources>
    <string name="app_name">ListViewSample2</string>
    <string name="dialog_title">注文確認</string>
    <string name="dialog_msg">選択された定食を注文します。よろしいですか。</string>
    <string name="dialog_btn_ok">注文</string>
    <string name="dialog_btn_ng">キャンセル</string>
    <string name="dialog_btn_nu">問い合わせ</string>
    <string name="dialog_ok_toast">ご注文ありがとうございました。</string>
    <string name="dialog_ng_toast">ご注文をキャンセルしました。</string>
    <string name="dialog_nu_toast">お問い合わせ内容をお知らせください。</string>
</resources>
```

■activity_main.xml

``` kotlin

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/lvMenu">
    
</ListView>
```

■MainActivity.kt
リストビューの準備

``` kotlin


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

        val lvMenu = findViewById<ListView>(R.id.lvMenu)
        val menuList = mutableListOf("ごはん","ラーメン","チキン","野菜","漬物")
        val adapter = ArrayAdapter(this@MainActivity,android.R.layout.simple_list_item_1,menuList)
        lvMenu.adapter = adapter
        lvMenu.onItemClickListener = ListItemClickListener()
    }
```

#■ダイアログを表示するには！

▼ダイアログの生成クラスを準備
[java]フォルダの中[com.websarva.wings.android.アプリ名前]を右クリック
[New] -> [Kotlin File/Class]を選択

Name欄にクラス名
ドロップダウンでClassが選択されている
Enterキーで作成

###1
ダイアログの生成クラスで
■DialogFragmentを継承したクラスをつくる。

import androidx.appcompat.app.AlertDialogこれを足すの忘れないように

``` kotlin
import androidx.fragment.app.DialogFragment
import androidx.appcompat.app.AlertDialog

class Hoge:DialogFragment() {}
```

###2
■onCreateDialog()メソッドを準備
ダイアログを作るメソッド返り値にDialogを持つ

``` kotlin

class Hoge:DialogFragment(){
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {}
}
```

###3
■activityプロパティを準備
activityプロパティはnullが許されたプロパティNullableプロパティです。
activity?.let{}でnullかどうか判断します。
nullでなければ中身が通ります。

``` kotlin
class Hoge:DialogFragment() {
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

  //アクティビティ(画面)がnullじゃなければ
  val dialog = activity?.let{} 
}
```

###4
■AleatDialog.Builder()を準備
引数にアクティビティを渡す。
activity?.let{}の中ではアクティビティがitに変わるのでitを渡している。
activityプロパティの中身を作っていきます。

``` kotlin
class Hoge:DialogFragment() {
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

  val dialog = activity?.let{ 
  //引数にitを渡している。
  val builder = AleatDialog.Builder(it)
 }
}
```


###5
■4で作ったbuilderオブジェクトにタイトルとメッセージの設定をします。
ダイアログのレイアウトを作っていきます。

ここがコンテンツエリアになります。
メッセージについては確実に設定する。
タイトルはどっちでもいい
引数をR値で渡す場合はstring.xmlで準備した文字を渡す。

``` kotlin
class Hoge:DialogFragment() {
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

  val dialog = activity?.let{ 
  val builder = AleatDialog.Builder(it)
  
  //変数に入れ込んだbuilderにsetしていく
  builder.setTitle(R.string.dialog_title)
  builder.setMessage(R.string.dialog_msg)
 }
}
```

###6
アクションボタンを設定する。
▼setPositiveButton(引数1,引数2)
▼setNegativeButton(引数1,引数2)
▼setNeutralButton(引数1,引数2)

■引数1
ボタンの文字
■引数2
ボタンを押すとどうなるかリスナクラスを渡します。

``` kotlin
class Hoge:DialogFragment() {
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

  val dialog = activity?.let{
  val builder = AleatDialog.Builder(it)
  
  builder.setTitle(R.string.dialog_title)
  builder.setMessage(R.string.dialog_msg)

  //引数2には後ほど作るボタンのリスナクラスを入れてます。(ボタンのアクション時の処理)
  builder.setPositiveButton(R.string.dialog_btn_ok,DialogButtonClickListener())
  builder.setNegativeButton(R.string.dialog_btn_ng,DialogButtonClickListener())
  builder.setNeutralButton(R.string.dialog_btn_nu,DialogButtonClickListener())
 }
}
```

###7
■ダイアログオブジェクトを生成する。

buiderにsetしてレイアウトを作ってきました。
それをcreate()メソッドを使ってダイアログオブジェクトを完成させます。

完成したダイアログオブジェクトが戻り値としてletに入り変数dialogに入ります。

``` kotlin
class Hoge:DialogFragment(){
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

  val dialog = activity?.let{
  val builder = AleatDialog.Builder(it)
  
  builder.setTitle(R.string.dialog_title)
  builder.setMessage(R.string.dialog_msg)

  builder.setPositiveButton(R.string.dialog_btn_ok,DialogButtonClickListener())
  builder.setNegativeButton(R.string.dialog_btn_ng,DialogButtonClickListener())
  builder.setNeutralButton(R.string.dialog_btn_nu,DialogButtonClickListener())
  //create()で作ったダイアログオブジェクトが変数dialogに入ります。
  builder.create()
 }
}
```

###8
■onCreateDialg()メソッドの戻り値としてdialogをreturnします。

その際エルビス演算子?:を使ってアクティビティがnullだった場合のエラー処理を書きます。
return dialog?:以降にアクティビティがnullだった場合の処理を書きます。

IllegalStateException("アクティビティがnullだよ")
要求された操作に対して適切な状態ではありません。

``` kotlin
class Hoge:DialogFragment(){
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

  val dialog = activity?.let{
  val builder = AleatDialog.Builder(it)
  
  builder.setTitle(R.string.dialog_title)
  builder.setMessage(R.string.dialog_msg)

  builder.setPositiveButton(R.string.dialog_btn_ok,DialogButtonClickListener())
  builder.setNegativeButton(R.string.dialog_btn_ng,DialogButtonClickListener())
  builder.setNeutralButton(R.string.dialog_btn_nu,DialogButtonClickListener())
  //create()で作ったダイアログオブジェクトが変数dialogに入ります。
  builder.create()
 }
 return dialog?: throw IllegalStateException("アクティビティがnullだよ")
}

```

以降はボタンの処理

#■ ボタンの処理　リスナクラスを作る。

###1

■dialogのボタンリスナクラスはDialogInterface.OnClickListenerインターフェイスを使う。
onClick(dialog: DialogInterface, which: Int)メソッドをオーバーライドして使います。

▼第2引数which
タップされたボタンを表す定数が渡される。

定数
Positive Button :: DialogInterface.Button_POSITIVE
Negative Button :: DialogInterface.Button_NEGATIVE
Neutral Button :: DialogInterface.Button_NEUTRAL

これをwhen式でボタンによっての処理を分岐していきます。
getString()メソッドでString.xmlの文字列を取得します。
最終的にToastでメッセージを表示します。


``` kotlin
private inner class DialogButtonClickListener: DialogInterface.OnClickListener {
  override fun onClick(dialog: DialogInterface, which: Int) {
   //トーストで表示するメッセージの空箱
   var msg = ""
  //第2引数を渡してボタンによって処理を分岐
   when(which) {
   //Positiveボタンが押された時の処理
   DialogInterface.Button_POSITIVE -> msg = getString(R.string.dialog_ok_toast)
   //Negativeボタンが押された時の処理
   DialogInterface.Button_NEGATIVE -> msg = getString(R.string.dialog_ng_toast)
   //Neutralボタンが押された時の処理
   DialogInterface.Button_NEUTRAL -> msg = getString(R.string.dialog_nu_toast)
   }
   //when式によって押されたボタンによってmsgに入るメッセージが違うそれをtoastで表示
   Toast.makeText(activity,msg,Toast.LENGTH_LONG).show()
  }
}
```

#■作ったダイアログをリストビューのタップ処理に！

■MainActivity

▼AdapterView.OnItemClickListenerインターフェイスを使う
onItemClick()メソッドをオーバーライドして使う
リストのItemがタップされたら


``` kotlin

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

      //省略
    //リストビューにリスナクラスを設定()
    lvMenu.onItemClickListener = ListItemClick()
    }
private inner class ListItemClick: AdapterView.OnItemClickListener {
 override fun onitemClick(parent: AdapterView<>, view: View,position:Int, id: Long){
  //ダイアログを作ったクラスをインスタンス化
  val dialogFlagment = OrderConfirmDialogFragment()
  //ダイアログを表示
  dialogFrafment.show(supportFragmentManager,"OrderConfirmDialogFragment")
  }
 }
}
```

これで完成です。

![Androidリストビュー.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/9d78fe50-940d-a703-3a3a-2819f5e7bcd0.gif)