个性化是Android的一大特点,根据用户习惯不同app应提供修改设置的页面。因此app需要面对大量需要持久化的变量。引入 Preference 库来实现这一需求
原有的Preference包已被弃用,建议使用AndroidX下的Preference
在app.build.gradle
中添加以下依赖
dependencies {
// ...
implementation 'androidx.preference:preference:1.1.0'
}
首先在res新建xml
资源文件,在里面新建一个以<PreferenceScreen>
开头的xml文件
<!-- preferences.xml -->
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<SwitchPreferenceCompat
app:key="notifications"
app:icon="@drawable/ic_android_black_24dp"
app:title="开关" />
<Preference
app:key="feedback"
app:title="发送反馈"
app:summary="上传技术Issues或提供建议"/>
<PreferenceCategory
app:key="category_0"
app:summary="分组标题"
app:title="分组0">
<SwitchPreferenceCompat
app:key="switch_0"
app:summaryOff="关闭时提示"
app:summaryOn="开启时提示"
app:summary="全局提示优先级低于上面两条"
app:title="开关0"/>
<EditTextPreference
app:key="edit_0"
app:summary="输入框,输入内容"
app:title="输入0"/>
<Preference
app:key="sub_page"
app:title="点击进入二级设置"
app:summary="自动加入返回栈"
app:fragment="com.cloud_hermits.cameraxtest.fragment.SubSettingsFragment"/>
</PreferenceCategory>
</PreferenceScreen>
如上所示的文件,提供了如下界面
其层级关系可以参考View
与ViewGroup
。在这里,PreferenceCategory
之于ViewGroup
,Preference
之于View
,
xmlns:app="http://schemas.android.com/apk/res-auto"
key
。因为所有设置项都继承自它,所以实际上所有的设置项也都必须设置key。其中,app:key
为其标识符,icon
为该设置项的图标。app:title
设置标题,app:summary
设置其描述。app:summaryOff
和app:summaryOn
分别设置其在开启和关闭状态下的描述。优先级高于单纯的app:Summary
Preference需要通过Fragment来实现展示。创建一个继承自PreferenceFragmentCompat
的类(文件或public static
修饰),并在其回调中导入刚刚编写的xml文件
public class SettingsFragment extends PreferenceFragmentCompat{
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
}
}
class SettingsFragment: PreferenceFragmentCompat(){
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?){
setPreferencesFromResource(R.xml.preferences, rootKey)
}
}
接下来,像添加普通Fragment一样将其加入Activity即可
若设置选项多到使用<PreferenceCategory>
依旧过于复杂的地步,可以考虑分成多个界面进行展示
<PreferenceScreen>
<!-- ... -->
<Preference
app:key="sub_page"
app:title="点击进入二级设置"
app:summary="自动加入返回栈"
app:fragment="com.cloud_hermits.cameraxtest.fragment.SubSettingsFragment"/>
</PreferenceScreen>
点击该Preference后,将会跳转至app:fragment
属性指向的Fragment(完整包名),并自动添加进返回栈。也就是说无需额外代码,即可实现用户使用返回键跳转到上级设置页面。
当然也可以在代码内通过Preference#setFragment(String fragment)
实现跳转
当用户点击关联Fragment的设置项时,会调用接口方法PreferenceFragmentCompat#OnPreferenceStartFragmentCallback#onPreferenceStatFragment(PreferenceFragmentCompate, Preference)
。建议托管在Activity中实现,以便在配置页面跳转时更新工具栏标题或其它工作.
通过在xml文件中定义的app:key
属性,可以在Fragment中通过方法来获取实例
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey){
setPreferencesFromResource(R.xml.preferences, rootKey);
//获取Key为 switch_0 的设置项
SwitchPreferenceCompat switch0 = findPreference("switch_0");
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?){
setPreferenceFromResource(R.xml.preferences, rootKey)
var switch0: SwitchPreferenceCompat? = findPreference("switch_0")
}
有时候有些设置项只有在特定条件下才开放设置。可以通过属性app:isPreferenceVisible
和app:enable
来进行可见性和禁用状态的设置也可以在代码中通过setVisible(boolean)
\ setEnable
来进行设置
获取到Preference实例后,可以为其设置SummaryProvider
进行动态描述的设置。Android提供了两个简单的实现以满足普通需求
ListPreference.SimpleSummary.SimpleSummaryProvider
和EditTextPreference.SimpleSummaryProvider
,可以通过Reference的属性app:useSimpleSummaryProvider
设置,或通过代码使用。其会通过summary描述展示已经设置的值,若该值为空,则显示“Not set”。
代码设置:
listPreference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
editTextPreference.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());
listPreference.summaryProvider = ListPreference.SimpleSummaryProvider.getInstance()
editTextPreference.summaryProvider = EditTextPreference.SimpleSummaryProvider.getInstance()
当然,也可以自己实现SummaryProvider<T extent Preference>
并将其设置进Preference
可以在<Preference>
中嵌套<intent>
标签来实现跳转。
<Preference
app:key=”activity”
app:title="Launch activity">
<intent
android:targetPackage="com.example"
android:targetClass="com.example.ExampleActivity"/>
</Preference>
上述代码会跳转至ExampleActivity页面,或者也可以直接在Preference
使用setIntent(Intent)
<intent>
标签同样可以嵌套<extra>
标签,以实现隐式跳转
默认情况下,Preference使用SharedPreferences
进行保存,保存在PreferenceManager.getDefaultSharedPreferences()
中。检索方式如下
//官方示例 java
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
String name = sharedPreferences.getString(“signature”, "");
//官方示例 kotlin
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this /* Activity context */)
val name = sharedPreferences.getString("signature", "")
当然也可以通过实现并拓展PreferenceDataStore
类来实现自定义数据存储(应注意ANR问题)。通过Preference#setPreferenceDataStore(PreferenceDataStore)
或PreferenceManager#setPreferenceDataStore(PreferenceDataStore)
设置个别/全局的数据存储方式。
若调用尚未实现的方法,会导致抛出UnsupportedOperationException
异常。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章