Android Preference 设置全攻略

Android 设置是每个App必不可小的东西,看似很简单,但是初学不熟悉的很花时间去研究,特别样式兼容方面,以及有自定义设置的需求,下面是对用法做一个总结

Preference结构

界面结构看下图


界面主要由PrefercenScreen、PreferenceCategory和Preference三个主要部分组成
– PrefercenScreen最根的部分;
– PreferenceCategory是每个设置的分组;
– Preference是具体到每个设置元素;

XML文件

XML结构层级大致如图

<android.support.v7.preference.PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <android.support.v7.preference.PreferenceCategory
        android:title="preference v7">
        <android.support.v7.preference.CheckBoxPreference
            android:defaultValue="false"
            android:key="key_checkbox"
            android:summaryOff="@string/theme_light"
            android:summaryOn="@string/theme_dark"
            android:title="Checkbox"
            />
    </android.support.v7.preference.PreferenceCategory>
</android.support.v7.preference.PreferenceScreen>

类库

由于Android版本升级,Preference加上原生的供有四个版本类库,根据API的最低版本使用相应的类库,如果你的最低版本是11,使用PreferenceFragment的话就可不使用兼容库。下面对每个包层次整理一下

android.preference

PreferenceFragment
如果你的安卓最低版本面向11以上的,可以直接使用这个包为基础

android.support.v7.preference

android.support.v14.preference

android.support.v17.preference

这个包主要面向电视,暂时不深入研究,具体特性迟点再补充

Preference介绍

Preference
  • Preference 是所有设置项目的基类,很多属性都从这个类派生出来。
    它有android.preference.Preference和 android.support.v7.preference.Preference两个部分,大致用法相同,详细请参考文档;

  • 从文档可了解到android.preference.Preference 是针对PreferenceActivity
    ListView旧款偏好而设计,而android.support.v7.preference.Preference则适合
    用RecyclerView重新设计的PreferenceFragmentCompat,使用的时候对号入座就可以了;

  • 他们都是内置 SharedPreferences 以及对应的android:key属性来存储数据

关键属性:
– android:title,显示的标题;
– android:summary,标题下面对应的摘要;
– android:key,存储数据的键值;
– android:dependency: 这是一个键值,如果设置,必须依赖key这个才可以启用;

PreferenceScreen

它是所有偏好的根节点:
– 当它放在根部的时候是不显示的;
– 当它放在节点位置的显示,点击显示它的子元素;
如图:


PreferenceCategory

这个很简单就是一个分组的效果,只要设置好标题就可以了

MultiSelectListPreference

显示多选对话框,存储多项数据,关键属性:
– android:entries,显示栏目数据
– android:entryValues,栏目对应的值
– android:defaultValue 默认值,数组

通过上面的架构发现,到v7下面没有了MultiSelectListPreference,只有
MultiSelectListPreferenceDialogFragmentCompat,原因不得而知,估计是google想只提供对话框给开发者自己实现,但是到了v14下面MultiSelectListPreference回归了,原因不深入,直接使用就可以。

<MultiSelectListPreference
            android:defaultValue="@array/deflistItems"
            android:dialogTitle="MultiSelectListPreferenceDialog"
            android:entries="@array/listItems"
            android:entryValues="@array/listItems"
            android:key="key_multi_select_list_pref"
            android:summary="MultiSelectListPreference summary"
            android:title="MultiSelectListPreference"
  />

效果图

ListPreference

显示单选对话框,存储单项数据,关键属性:
– android:entries,显示栏目数据
– android:entryValues,栏目对应的值
– android:defaultValue 默认值

ListPreference 存在原生和v7包下面,v14只保留ListPreferenceDialogFragment

<ListPreference
     android:defaultValue="Item4"
     android:dialogTitle="ListPreferenceDialog"
     android:entries="@array/listItems"
     android:entryValues="@array/listItems"
     android:key="key_list_pref"
     android:summary="ListPreference summary"
     android:title="ListPreference"
     />

效果图:

EditTextPreference

EditTextPreference继承DialogPreference,然后编辑对户框可以输入文字并保存
EditTextPreference存在原生和v7包下面,v14只保留EditTextPreferenceDialogFragment
关键属性:
– android:defaultValue 默认值

 <EditTextPreference
            android:defaultValue="defaultValue"
            android:key="key_edittext"
            android:summary="EditTextPreference summary"
            android:title="EditTextPreference"
 />

效果图

CheckBoxPreference

选择框偏好,CheckBoxPreference存在原生和v7包下面
关键属性:
– android:defaultValue 默认值
– android:summaryOff: 取消选择的时候显示文字
– android:summaryOn:选择的时候显示文字

 <CheckBoxPreference
            android:defaultValue="false"
            android:key="key_checkbox"
            android:summaryOff="@string/theme_light"
            android:summaryOn="@string/theme_dark"
            android:title="Checkbox"
    />

效果图

SwitchPreference

开关编好,使用也比较简单,原生和v14都有,v7下面是SwitchPreferenceCompat
关键属性:
– android:defaultValue 默认值
– android:summaryOff: 关闭时候显示文字
– android:summaryOn: 开启时候显示文字
– android:switchTextOff: 关闭时候开关上显示的文字
– android:switchTextOn:开启时候开关上显示的文字

<SwitchPreference
            android:defaultValue="false"
            android:switchTextOff="@string/theme_light"
            android:switchTextOn="@string/theme_dark"
            android:summaryOff="@string/theme_light"
            android:summaryOn="@string/theme_dark"
            android:title="SwitchPreference"/>

        <android.support.v7.preference.SwitchPreferenceCompat
            android:defaultValue="false"
            android:summaryOff="@string/theme_light"
            android:summaryOn="@string/theme_dark"
            android:switchTextOff="@string/theme_light"
            android:switchTextOn="@string/theme_dark"
            android:title="SwitchPreferenceCompat"/>

        <android.support.v14.preference.SwitchPreference
            android:defaultValue="false"
            android:key="key_dark_theme_v14"
            android:switchTextOff="@string/theme_light"
            android:switchTextOn="@string/theme_dark"
            android:summaryOff="@string/theme_light"
            android:summaryOn="@string/theme_dark"
            android:title="v14.preference.SwitchPreference"/>

经过测试,SwitchPreferenceCompat 全平台material design风格,开关样式如图看出
android.support.v14.preference.SwitchPreference和SwitchPreference Android5.0以下,按钮还是保留老样式,可以显示文字

效果图

RingtonePreference

铃声选择编好,只存在原生包上面
关键属性:
android:ringtoneType 铃声类型分四个选项:
– alarm:只显示闹钟声
– all: 显示所有
– notification: 只显示通知声
– ringtone 只显示铃声
android:showDefault: 是否显示默认选项,默认显示

android:showSilent 是否显示静音选项,默认显示

效果:

SeekBarPreference

微调偏好设置,SeekBarPreference只在v7包下存在
关键属性
app:showSeekBarValue: 是否显示进度数字
android:defaultValue: 默认值

 <android.support.v7.preference.SeekBarPreference
       android:key="key_seekbar"
       android:title="SeekBarPreference"
       app:showSeekBarValue="false"
       android:defaultValue="50"
      />

DropDownPreference

和ListPreference差不多,只不过是用下拉的样式代替对话框

<android.support.v7.preference.DropDownPreference
            android:defaultValue="Item4"
            android:dialogTitle="DropDownDialog"
            android:entries="@array/listItems"
            android:entryValues="@array/listItems"
            android:summary="DropDownPreference summary"
            android:title="DropDownPreference"
    />

效果图:

Preference自定义

以上偏好都不能满足的时候需要自定义,例如我的App软件上定义了一个关于的对话框
先看看效果是这样的:

  • 我们需要定义preference,通过继承自定义DialogPreferece,代码如下
public class AboutDialogPreference extends DialogPreference {
public static final String KEY_ABOUT_DIALOG = "key_about_dialog";
public AboutDialogPreference(Context context, AttributeSet attrs) {
  super(context, attrs);
  setKey(KEY_ABOUT_DIALOG);
  setTitle(R.string.about);
  setSummary(getContext().getString(R.string.app_name) + PkgUtils.get(getContext()).getAppVerName());
 }
}
  • 然后自定义对话框
    关键一点,newInstance()必须带上AboutDialogPreference的key,否则会出错
public class AboutPreferenceDialogFragment extends PreferenceDialogFragmentCompat {

  public static AboutPreferenceDialogFragment newInstance() {
  Bundle args = new Bundle();
  args.putString(ARG_KEY, AboutDialogPreference.KEY_ABOUT_DIALOG);
  AboutPreferenceDialogFragment fragment = new AboutPreferenceDialogFragment();
  fragment.setArguments(args);
  return fragment;
 }

  @Override
  protected View onCreateDialogView(Context context) {
  return View.inflate(context, R.layout.fragment_preference_about_dialog, null);
  }

  @Override
 protected void onBindDialogView(View view) {
  AppCompatTextView messageView = (AppCompatTextView) view;
  messageView.setText(getInfo());
  }

  private String getInfo() {
  String systemInfo = getString(R.string.model) + " " + Build.MODEL + "\n"
  + getString(R.string.system) + " Android "
  + Build.VERSION.RELEASE + "(API:" + Build.VERSION.SDK_INT + ")";
  PackageInfo info = PkgUtils.get(getContext()).getPackageInfo(getContext().getPackageName());
  String pkg = info != null ? info.versionName + (BuildConfig.DEBUG ? " debug" : "") : "";
  return getString(R.string.about_intro, getString(R.string.app_name) + pkg, systemInfo);
  }

  @Override
  protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
 builder.setIcon(R.mipmap.ic_launcher);
 builder.setTitle(R.string.about);
  builder.setNeutralButton(R.string.privacy_policy, (dialogInterface, i) -> {
  TXWebViewActivity.browse(getContext(),
  getContext().getString(R.string.privacy_policy),
  TXApplication.URL_PRIVACY, false);
  });
  builder.setPositiveButton(R.string.app_detail, (dialogInterface, i) -> { IntentUtils.get(getContext()).showAppDetails(getContext().getPackageName());
  });
}

 @Override
  public void onDialogClosed(boolean positiveResult) {
  }
}
  • 最后在SettingFragment主界面做处理
    在onDisplayPreferenceDialog里面判断并且实例化AboutPreferenceDialogFragment,然后显示对话框
public class SettingFragment extends PreferenceFragmentCompat{

@Override
 public void onDisplayPreferenceDialog(Preference preference) {
  DialogFragment dialogFragment = null;
  if (preference instanceof AboutDialogPreference) {
  dialogFragment = AboutPreferenceDialogFragment.newInstance();
 }
  if (dialogFragment != null) {
  dialogFragment.setTargetFragment(this, 0);
  dialogFragment.show(this.getFragmentManager(), "");
  } else {
  super.onDisplayPreferenceDialog(preference);
  }
}
}

总结

  • Preference掌握关键必须理清类的集成关系,主要是Preference,分对话框Preference和普通双态Preference,并且掌握他们的扩展的
  • PreferenceActivity和PreferenceFragment模式的差异
  • 理清每个支持库的差异,多在模拟器实践验证
  • 掌握关键属性,多看文档

留下评论

电子邮件地址不会被公开。 必填项已用*标注