【Kotlin】Kotlin ~ 基本編 / Enum・列挙型関連 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2020/07/23/000000

の続き。

Kotlin に限らず、Enumをよく使うのでまとめる

目次

【1】Enum の 基本
【2】Enum の 逆引き

【1】Enum の 基本

構文

enum class <EnumName> {
   ENUM1,
   ENUM2,
   ENUM3
}

【2】Enum の 逆引き

* スピーナのPositionからEnumを逆引きしたい
* Enum から 設定値を取得し、設定ファイルに保存する

などをしたい場合に調べたら、以下のサイトがあったので
参考に実装してみた

https://bsblog.casareal.co.jp/archives/4107

サンプル

 目覚ましアプリを作成した際の設定で
スヌーズ(値、単位)を保存するサンプル

列挙型:SnoozeValue.kt

packeage sample.alarm.settings

enum class SnoozeValue(index: Int, value: Int, text: String) {
    ONE(0, 1, "1"),
    FIVE(1, 5, "5"),
    TEN(2, 10, "10"),
    FIFTEEN(3, 15, "15"),
    THIRTY(4, 30, "30"),
    SIXTY(5, 60, "60");

    val index = index
    val value = value
    val text = text

    companion object {
        const val KeyValue = "SnoozeValue"
        private val Default: SnoozeValue = FIVE

        fun getDefaultValue(): Int {
            return Default.value
        }

        fun getEnumByIndex(index: Int): SnoozeValue =
            values().find {
                it.index == index
            } ?: Default

        fun getEnumByValue(value: Int): SnoozeValue =
            values().find {
                it.value == value
            } ?: Default

        fun getEnumByText(text: String): SnoozeValue =
            values().find {
                it.text == text
            } ?: Default
    }
}

列挙型:SnoozeUnit.kt

packeage sample.alarm.settings

import java.util.*

enum class SnoozeUnit(index: Int, value: Int, text: String) {
    SECOND(0, Calendar.SECOND, "Second"),
    MINUTE(1, Calendar.MINUTE, "Minute"),
    HOUR(2, Calendar.HOUR_OF_DAY, "Hour");

    public val index = index
    public val value = value
    public val text = text

    companion object {
        const val KeyValue = "SnoozeUnit"
        private val Default:SnoozeUnit = MINUTE

        fun getDefaultValue(): Int {
            return Default.value
        }

        fun getEnumByIndex(index: Int): SnoozeUnit =
            values().find {
                it.index == index
            } ?: Default

        fun getEnumByValue(value: Int): SnoozeUnit =
            values().find {
                it.value == value
            } ?: Default

        fun getEnumByText(text: String): SnoozeUnit =
            SnoozeUnit.values().find {
                it.text == text
            } ?: Default
    }
}

SettingHandler.kt

import android.content.Context
import androidx.appcompat.app.AppCompatActivity.MODE_PRIVATE

class SettingHandler(context: Context) {
    private val preference = context.getSharedPreferences(
        "alarm", MODE_PRIVATE
    )

    fun save(snoozeValue: SnoozeValue, snoozeUnit: SnoozeUnit) {
        this.save(snoozeValue)
        this.save(snoozeUnit)
    }

    fun save(snoozeValue: SnoozeValue) {
        this.preference.edit().apply {
            putInt(SnoozeValue.KeyValue, snoozeValue.value)
            commit()
        }
    }

    fun save(snoozeUnit: SnoozeUnit) {
        this.preference.edit().apply {
            putInt(SnoozeUnit.KeyValue, snoozeUnit.value)
            commit()
        }
    }

    fun getSnoozeValueEnum(): SnoozeValue {
        return SnoozeValue.getEnumByValue(this.getSnoozeValue())
    }

    fun getSnoozeUnitEnum(): SnoozeUnit {
        return SnoozeUnit.getEnumByValue(this.getSnoozeUnit())
    }

    fun getSnoozeValue(): Int {
        return this.preference.getInt(
            SnoozeValue.KeyValue,
            SnoozeValue.getDefaultValue()
        )
    }

    fun getSnoozeUnit(): Int {
        return this.preference.getInt(
            SnoozeUnit.KeyValue,
            SnoozeUnit.getDefaultValue()
        )
    }
}

SettingsActivity.kt

import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.AdapterView
import android.widget.Spinner
import sample.alarm.settings.SnoozeUnit
import sample.alarm.settings.SnoozeValue
import kotlinx.android.synthetic.main.activity_settings.*

class SettingsActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_settings)

        val snoozeValue =
            super.settingHandler.getSnoozeValueEnum()
        val snoozeUnit =
            super.settingHandler.getSnoozeUnitEnum()

        this.snoozeValueSpinner.setSelection(snoozeValue.index, true)
        this.snoozeUnitSpinner.setSelection(snoozeUnit.index, true)

        super.settingHandler.save(snoozeValue, snoozeUnit)

        this.snoozeValueSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                val targetSpinner = parent as Spinner
                if (!targetSpinner.isFocusable) {
                    targetSpinner.isFocusable = true;
                    return;
                }
                val selectedSnoozeValue = SnoozeValue.getEnumByIndex(position)
                settingHandler.save(selectedSnoozeValue)
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {
                // Do nothing
            }
        }

        this.snoozeUnitSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                val targetSpinner = parent as Spinner
                if (!targetSpinner.isFocusable) {
                    targetSpinner.isFocusable = true;
                    return;
                }
                val selectedSnoozeUnit = SnoozeUnit.getEnumByIndex(position)
                settingHandler.save(selectedSnoozeUnit)
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {
                // Do nothing
            }
        }
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        super.onCreateOptionsMenu(menu)

        val inflater = menuInflater
        inflater.inflate(R.menu.sub_menu, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.homeItem -> {
                super.moveToMain()
                true
            }
            else -> {
                super.onOptionsItemSelected(item)
            }
        }
    }
}

関連記事

画面コンポーネント / RadioButton etc ~ 選択肢 ~
https://dk521123.hatenablog.com/entry/2013/10/08/000037
設定ファイルの保存 ~ SharedPreferences ~
https://dk521123.hatenablog.com/entry/2013/10/02/005640
Kotlin ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2018/09/13/001546
Kotlin ~ 基本編 / 配列・コレクション ~
https://dk521123.hatenablog.com/entry/2020/07/07/000000
Kotlin ~ 基本編 / クラス ~
https://dk521123.hatenablog.com/entry/2020/07/23/000000