抬头仰望星空,是否能发现自己的渺小。

伪斜杠青年

人们总是混淆了欲望和理想

自定义DialogPreference

最近定义了很多Preference,实在话这块儿挺大的,谷歌给的那套不合适基本上就得自己重写一套layout,有时候只是写layout倒是也没什么,就是还有时候要加点高级布局。

一般定义Preference有两种,一种是无二级页面,仅展示title summery或者开关,这种比较好处理。还有一种是带二级页面的,比如点击后弹出一个弹窗,弹窗上的内容也比较高级或者复杂,这种一般写起来也复杂。这里大概总结下,但不贴全。

普通条目Preference

对于普通的SwitchPreference等,继承Preference,将固定的几个layout id对上即可。

简单步骤:

class CustomPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {

    private var initialValue: String? = null

    init {
        //界面显示的UI布局
        layoutResource = R.layout.preference_layout
        //跳转的fragment
        //fragment = NewFragment.Fragment::class.java.name
        //需要携带的数据
        //extras["key"] = "value"
    }

    override fun onGetDefaultValue(a: TypedArray, index: Int): Any? {
        return a.getString(index)
    }

    override fun onSetInitialValue(defaultValue: Any?) {
        initialValue = getPersistedString(defaultValue as? String)
    }

    override fun onAttached() {
        super.onAttached()
        summary = getPersistedString(initialValue)
    }
}

initialValue就是根据key获取的一个数据,配合defaultValue使用,然后其次一般在onAttached时才进行summary的赋值,这里可以配合自定义的layout中的其他控件去填充数据。这里demo只是string类型,也可以是其他类型,把getPersistedString改了就行。

存在二级弹窗的Preference

首先要让这个首选项所在的fragment支持自定义,也就是说需要先处理PreferenceFragmentCompat,然后大概思路就是重写PreferenceFragmentCompat的onDisplayPreferenceDialog方法,大致如下:

override fun onDisplayPreferenceDialog(preference: Preference) {
    if (preference is IBaseDialogPreference) {
        preference.displayPreferenceDialog(this)
    } else {
        super.onDisplayPreferenceDialog(preference)
    }
}

这里有两个未知的东西IBaseDialogPreference、preference.displayPreferenceDialog,其实容易理解,因为并没什么合适的方式直接定义DialogPreference,而且其中还有很多麻烦,倒不如自己实现一套方案去显示我们自定义的fragment/dialog。

下一步就知道了,意思是我们的DialogPreference需要实现一个接口IBaseDialogPreference,并实现其displayPreferenceDialog方法,接口如下:

interface IBaseDialogPreference {
fun displayPreferenceDialog(fragment: PreferenceFragmentCompat)
}

类如下:

abstract class BaseDialogPreference(context: Context, attrs: AttributeSet? = null) :
        DialogPreference(context, attrs), IBaseDialogPreference {

    abstract fun onCreateDialogFragment(): PreferenceDialogFragmentCompat

    override fun displayPreferenceDialog(fragment: PreferenceFragmentCompat) {
        val df = onCreateDialogFragment()
        if (df.arguments == null) {
            df.arguments = Bundle()
        }
        df.arguments?.putString(ARG_KEY, key)
        df.setTargetFragment(fragment, 0)
        df.show(fragment.fragmentManager, "dialog.fragment.$key")
    }
}

然后大概就清晰了,去写个继承PreferenceDialogFragmentCompat的fragment即可。

Tips:

对于二级preference,其实还有更简单的办法,就是将preference的点击事件直接换成显示fragment即可,不需要继承也不需要封装。只需要做fragment的状态定义。(记得自己写key value的保存)

参考:https://www.jianshu.com/p/02d2839606aa


0条评论

发表评论