自定义android偏好界面——Preference解析与自定义

时间:2024-03-22 16:09:15

    Preference用于android设置偏好界面,像设置界面就是用这个写的,其实就是xml文件,放在res/xml中,方便简单,如果直接用,有时候不符合自己App的风格、主题。下面我们就以android.support.v7.preference.ListPreference为例:

自定义android偏好界面——Preference解析与自定义

上面就是ListPreference的所有属性,这里有个问题,mValueSet又是什么:

自定义android偏好界面——Preference解析与自定义

mValueSet只在这里方法里出现,只有初始化的时候为false,后面一直为true了,说明这是个判断是否有值的一个Boolean,

回到问题,该怎么自定义Preference的样式,浏览所有的代码,在ListPreference中并没有涉及到样式这个字眼,那么就往父类找,DialogPreference

自定义android偏好界面——Preference解析与自定义

明显,看到这些属性都只是关于弹出的Dialog的(后文会说怎么自定义Preference弹出的Dialog样式),明显该类里面也没有关系自定义样式的属性,那再往前面看它的父类Preference

在Preference.java中在136行有这样的一个属性private int mLayoutResId = R.layout.preference;看名称就知道,这个应该就是Preference的布局了,那么还有什么地方出现了这个属性呢

自定义android偏好界面——Preference解析与自定义

可以看出mLayoutResId这个是可以通过xml文件设置的,关键就是怎么跟preference上面的数据(文字,图片)相关联呢

在preference中正好有onBindViewHolder方法,看着名字就知道这是绑定的数据的方法,如果是想自定义样式,则自己的布局文件如果要显示title必须要有id="@android:id/title"的TextView。。。其它的类似,自己可以看。

下面来分析下如何自定义弹出的Dialog的样式

    上文以分析到,在DialogPreference类中,各个属性都是用来描述Dialog的,mDialogLayoutResId也就是布局id了
自定义android偏好界面——Preference解析与自定义

    从这里可以知道自定义Dialog可以从这里入手直接在xml这里修改Dialog的布局,另一个问题又出来了,那怎么跟布局控件绑定呢,要知道Dialog出来是通过点击Preference,那么直接看点击后的事件,在Preference的onBindViewHolder方法中,设置了点击事件,在DialogPrefrence的onClick触发的是:getPreferenceManager().showDialog(this);触发的是PreferenceManager.showDialog方法,那么这个mOnDisplayPreferenceDialogListener是什么呢,在PreferenceManager文件中OnStart()中看到有set方法,通过该方法,可以找到就是PreferenceFragmentCompat类

    showDialog其实就是执行了 PreferenceFragmentCompat的onDisplayPreferenceDialog方法,那么我们来看看该方法到底是实现了什么

自定义android偏好界面——Preference解析与自定义

从上面代码就可以发现,这里有三个弹出Dialog的方式,一:getCallbackFragment返回的Fragment继承OnPreferenceDisplayDialogCallback,然后通过onPreferenceDisplayDialog这个方法;二:与一相似,只不过是通过Activity而已;三:直接重写onDisplayPreferenceDialog这个方法。

    我们先来看看它是怎么构建Dialog的,主要的就是后面这部分,我们就以ListPreferenceDialogFragmentCompat为例

ListPreferenceDialogFragmentCompat——>PreferenceDialogFragmentCompat——>DialogFragment

上面就是该类的继承关系,归根到底也就是个DialogFragment,我们先看ListPreferenceDialogFragmentCompat

自定义android偏好界面——Preference解析与自定义这里的setArguments其实就是把这个参数传给自己,保存起来,源码注释为// Construction arguments;顾名思义就是构造函数里面的参数

我们一步步来,先看父类PreferenceDialogFragmentCompat中的OnCreate的代码

自定义android偏好界面——Preference解析与自定义getTargetFragment得到的是什么呢?上面PreferenceFragmentCompat的onDisplayPreferenceDialog方法中有个地方标记好了,也就是说getTargetFragment得到的就是PreferenceFragmentCompat,我们再来看看子类ListPreferenceDialogFragmentCompat中OnCreate中的代码

自定义android偏好界面——Preference解析与自定义

getListPreference()就是取出传递过来的的preference 然后在强制转化为ListPreference。我们再跳转到父类,看其OnCreateDialog中代码,这里就是构建Dialog,到现在,DialogLayout才排上用场,OnCreateDialog中调用onCreateDialogView,然后再绑定控件,

自定义android偏好界面——Preference解析与自定义

这里用到了mDialogLayoutRes这个值,返回的是个Layout,在onBindDialogView使用到了这个Layout,
这里只是绑定了message的数据,其它的一些控件显示,是通过onPrepareDialogBuilder这个方法实现的
onPrepareDialogBuilder该方法是空的,交给子类实现
needInputMethod方法主要是为了必要的时候能弹出软键盘。

onBindDialogView就是绑定各个控件的,自定义则可以通过重写这个。整个分析到这也差不多结束了。

总结:

    只是自定义Preference,直接在xml的属性加上个layout就行,

    自定义dialog:

        1.可以在xml的属性加上dialogLayout,但控件的id要跟系统的一样

    2.可以在xml的属性加上dialogLayout,重写继承PreferenceFragmentCompat的Fragment中的onDisplayPreferenceDialog,新建一个继承PreferenceDialogFragmentCompat的类,重写onBindDialogView方法

     3.重写继承PreferenceFragmentCompat的Fragment中的onDisplayPreferenceDialog,新建一个继承DialogFragment的类,直接在OnCreateView中建立自己的Dialog