LoginSignup
0
1

More than 1 year has passed since last update.

【Kotlin研修3日目】SimpleAdapterを用いたアクティビティ間のデータ共有と画面遷移、レイアウトファイルでのリスナ定義

Last updated at Posted at 2021-06-04

SimpleAdapter

参考1: 研修2日目
参考2: SimpleAdapter
MutableList<MutableMap<String, *>>型のデータ構造をとるAdapterクラス。

MutableList

キーをもち、要素数が可変」なMutableMap<String, *>型のデータを、各インデックスに格納したリスト

SimpleAdapterの生成

定義

SimpleAdapter(
    context: Context!,
    data: MutableList<out MutableMap<String!, *>!>!,
    resource: Int
    from: Array<String>!
    to: IntArray!
)
// パラメータ
// context: コンテキストとなるアクティビティオブジェクト
// data: リスト形式ビューに反映するリストデータ
// resource: リスト形式ビューの各Itemのレイアウトを表現するR値
// from: MutableMapのキーのみを格納した配列
// to: Item内の複数のビュー(=TextView)を識別するR値(=ID)を格納した配列
// -> toで指定したビュー(=TextView)に対して、
//    fromで指定したキーに対応する値を格納

値を加工して表示するListView

MainActivity.kt
// 発展: 値を加工したListViewの生成

class MainActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        val nameList = createNameList()
        val from = arrayOf("name", "sex")
        val to = intArrayOf(R.id.tvName, R.id.imSex)
        // Adapterオブジェクトの生成
        val adapter = SimpleAdapter(
            applicationContext,
            nameList,
            R.layout.row,
            from,
            to
        )

        // AdapterにViewBinderオブジェクトをセット
        adapter.viewBinder = CustomViewBinder()
        // リストデータを紐づけるListViewの定義
        val lvPhones = findViewById<ListView>(R.id.lvNameList)
        // ListViewにAdapterオブジェクトをセット
        lvPhones.adapter = adapter
    }

    // 加工するリストデータを生成するメソッド
    private fun createNameList(): MutableList<MutableMap<String, Any>> {
        // 加工するリストデータを記述
        ...  // 最終的に"return <リストデータ>"を記述
    }

    // MutableMapの値を基にデータを加工するクラス
    private inner class CustomViewBinder: SimpleAdapter.ViewBinder {
        // MutableMapの値を基にデータを加工
        // -> ListView生成時に自動的に実行される
        override fun setViewValue(
            view: View,
            data: Any,
            textRepresentation: String
        ): Boolean {
            // データの加工処理
            ...  // 最終的に"return true/false"を記述
                 // true: データのバインドが実行された場合
                 // false: データのバインドが実行されなかった場合
        }
    }
}

画面の追加

参考: 研修1日目
アプリに表示される文字列を除き、アプリの1画面を構成しているのは、以下の3つ。

  1. アプリ内処理を担う、app/javaフォルダのアクティビティクラス(=.ktファイル)
  2. 画面構成を担う、app/res/layoutフォルダのレイアウトファイル(=.xmlファイル)
  3. 1.および2.を認識する、app/manifestsフォルダのAndroidManifest.xmlファイル

画面を追加する場合は、AndroidManifest.xmlファイルにactivityタグを記述する必要がある。
Android Studioは、New Activityの作成時に、アクティビティの追加にあたって必要な処理を自動的に行う。

Androidにおける画面遷移

遷移先の画面は、遷移元の画面の前面に表示される。
遷移先から戻る場合は、遷移先の画面が消滅し、背面に隠れていた遷移元の画面が表示される挙動をとる。

インテント(Intent)

参考: インテント
参考2: インテントのクラスメソッド
画面遷移にあたり、画面(=アクティビティ)を起動するクラス。
遷移元アクティビティと遷移先アクティビティの橋渡し役を担う。

Intentクラスのインスタンス化(実体化)

定義

Intent(packageContext: Context!, cls: Class<*>!)
// パラメータ
// packageContext: 遷移元のアクティビティオブジェクト(=コンテキスト)
// cls: Javaクラス化した遷移先アクティビティ
// -> KotlinのクラスをJavaに変換する場合は、"<Kotlinクラス名>::class.java"と記述

Intentオブジェクトへのデータの格納

インテントを通じてデータをやり取りする場合、Extraデータ(=追加情報)をIntentオブジェクトに追加する。

定義

putExtra(name: String!, value: String?): Intent
// パラメータ
// name: 格納するデータの名称
// value: 格納するデータ

遷移先アクティビティの起動(画面遷移)

定義

Activity.startActivity(intent: Intent!): Unit
// パラメータ
// intent: 画面遷移を実現するIntentオブジェクト

サンプルコード

MainActivity.kt
class MainActivity: AppCompatActivity() {
    ...
    // リスナクラス
    private inner class ListItemClickListener: AdapterView.OnItemClickListener {
        // "タップ"イベント検知時の処理(イベントハンドラ)
        override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            // "タップ"されたItemの定義
            // parent: AdapterView
            // getItemAtPosition(): 指定したIndex(position)のtext値を取得(返り値はAny型)
            val item = parent?.getItemAtPosition(position) as MutableMap<String, String>

            // 指定したキーの値
            val menuName = item["name"]
            val menuPrice = item["price"]

            // 画面遷移を実現するIntentオブジェクトの生成
            // Intent(packageContext:cls:): Intentオブジェクトの生成
            // packageContext: 遷移元のアクティビティオブジェクト(=コンテキスト)
            // cls: Javaクラス化した遷移先アクティビティ
            val intent2MenuThanks = Intent(
                this@MainActivity,
                MenuThanksActivity::class.java
            )

            // Intentオブジェクトへのデータの格納
            // putExtra(name:value:): Intentオブジェクトにデータを格納
            // name: 格納するデータの名称
            // value: 格納するデータ
            intent2MenuThanks.putExtra("menuName", menuName)
            intent2MenuThanks.putExtra("menuPrice", menuPrice)

            // 遷移先アクティビティの起動
            // Context.startActivity(intent:): Intentオブジェクトによる画面遷移の実行
            // intent: Intentオブジェクト
            startActivity(intent2MenuThanks)
        }
    }
}

apply関数を用いたIntentオブジェクトの生成・定義

MainActivity.kt
// 発展: apply関数の使用

// 本来はこっち
// 画面遷移を実現するIntentオブジェクトの生成
val intent2MenuThanks = Intent(
    this@MainActivity,
    MenuTahnksActivity::class.java
)
// Intentオブジェクトへのデータの格納
intent2MenuThanks.putExtra("menuName", menuName)
intent2MenuThanks.putExtra("menuPrice", menuPrice)

// apply関数(スコープ関数)を用いる場合
// -> applyブロック{...}内では、インスタンス変数(intent2MenuThanks)の記述が不要
val intent2MenuThanks = Intent(
    this@MainActivity,
    MenuTahnksActivity::class.java
).apply {
    putExtra("menuName", menuName)
    putExtra("menuPrice", menuPrice)
}

遷移先アクティビティの終了

定義

finish(): Unit

遷移先による遷移元の値取得

遷移元のデータはIntentオブジェクトが保持しているため、遷移先アクティビティintentプロパティを用いてデータを取得する。

文字列(String)

定義

Intent.getStringExtra(name: String!): String?
// パラメータ
// name: Intentオブジェクト(=intentプロパティ)に格納されたデータの名称

数値(Int)

定義

Intent.getIntExtra(name: String!, defaultValue: Int): Int
// パラメータ
// name: Intentオブジェクト(=Activity.intent)に格納されたデータの名称
// defaultValue: 取得するデータの初期値
// <- 指定したnameのデータが存在しない場合のnullを避ける

サンプルコード

MenuThanksActivity.kt
class MenuThanksActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Intentオブジェクトが保持するデータの取得
        val menuName = intent.getStringExtra("menuName")
        val menuPrice = intent.getStringExtra("menuPrice")

        // 値を反映する遷移先ビューの定義
        val tvMenuName = findViewById<TextView>(R.id.tvMenuName)
        val tvMenuPrice = findViewById<TextView>(R.id.tvMenuPrice)

        // 遷移先ビューの値(=TextView.text)の変更
        tvMenuName.text = menuName
        tvMenuPrice.text = menuPrice
    }
}

レイアウトファイルによるリスナ定義

参考: タップイベントのイベント処理
イベントを検知するリスナを定義する方法は以下の2つ。

  • Activityファイルでリスナクラスを定義
  • レイアウトファイルandroid:onClick属性を追加し、その属性値と一致するイベントハンドラ
    Activityファイルに記述
    フラグメントでは実装不可

サンプルコード

activity_menu_thanks.xml
<Button
    ...
    android:onClick="onBackButtonClick"  <!-- リスナ定義 -->
/>
MenuThanksActivity.kt
class MenuThanksActivity: AppCompatActivity() {
    ...
    // "タップ"イベント検知時の処理(イベントハンドラ)
    // ※実装にあたって制約が存在(後述)
    fun onBackButtonClick(view: View) {
        ...
    }
}

制約

レイアウトファイルリスナの定義を行う場合、イベントハンドラは以下の要件を満たす必要がある。

  • publicメソッドであること(Kotlinではpublicが規定値)
  • 返り値がない(=Unit型である)こと
  • View1つのみの引数をとること
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1