EditTextPreferenceで整数値を扱う

2021/01/24
Android
Kotlin
SharedPreference

Androidアプリ開発において、EditTextPreferenceでInt型のSharedPreferencesを取り扱う方法です。

環境

  • compileSdkVersion 29
  • minSdkVersion 21
  • androidx.core:core-ktx:1.3.2
  • androidx.preference:preference-ktx:1.1.1
  • androidx.legacy:legacy-preference-v14:1.0.0

EditTextPreferenceを拡張する

EditTextPreferenceをそのまま使うとString型としてSharedPreferenceに保存されます。
ですのでEditTextPreferenceを拡張してIntegerを扱えるようにします。

import android.content.Context
import android.util.AttributeSet
import androidx.preference.EditTextPreference
import java.lang.NumberFormatException

class IntegerEditTextPreference : EditTextPreference {

    constructor(context: Context?): super(context)
    constructor(context: Context?, attrs: AttributeSet?): super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyle: Int): super(context, attrs, defStyle)
    constructor(context: Context?, attrs: AttributeSet?, defStyle: Int, defStyleRes: Int): super(context, attrs, defStyle, defStyleRes)

    override fun getPersistedString(defaultReturnValue: String?): String {
        return getPersistedInt(0).toString()
    }

    override fun persistString(value: String?): Boolean {
        val intValue = try{
            Integer.parseInt(value!!)
        }
        catch (e: NumberFormatException){
            e.printStackTrace()
            0
        }
        return persistInt(intValue)
    }
}

値の範囲に制限を付けたり加工したい場合は、persistIntに放り込む値を加工すれば実現できます。入力が空の場合を考慮して、NumberFormatExceptionは受けるようにしましょう。

Fragmentの作成

res/xml/preferences.xmlなどのリソースファイルでは拡張したEditTextPreferenceを利用します。

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <com.hassakulab.preference.IntegerEditTextPreference
        android:key="HOGE"
        android:title="SampleIntegerPreference"
        android:summary="summary"
        />

</PreferenceScreen>

PreferenceFragmentの実装では、setOnBindEditTextListenerでEditTextの入力内容の制限などをします。
より細かな制御をするなら、TextEdit.addTextChangedListenerTextWatcherを実装すると良いでしょう。 リソースファイルでinputTypeなどを設定してもsetPreferencesFromResourceでViewを生成するタイミングで上書きされるようです。[1]

class SamplePreferenceFragment: PreferenceFragmentCompat(){
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences, rootKey)

        samplePreference = findPreference("HOGE")!!
        samplePreference.setOnBindEditTextListener { editText ->
            editText.inputType = InputType.TYPE_CLASS_NUMBER
            editText.maxLines = 1
        }
    }
}

  1. なんでこうなるか、ソースを読んで確認してないのでよくわかってないです。本当は確認した方がいい。バージョン依存? android - EditTextPreference - only numeric value inputType - isn't working - Stack Overflow

© 2019-2021 hassakulab.com, built with Gatsby