Android Preference 笔记
目录
1.从PreferenceScreen 中 删除某个Preference
2. Preference类图
3. Activity&Fragment / Preference&Fragment 组合使用
4. Actionbar (标题: 显示与隐藏 )
4.1 AppCompatActivity 默认有标题
4.2 PreferenceActivity 默认没有标题
5. Preference 点击回调事件(OnPreferenceClickListener 、OnPreferenceChangeListener)
6. persistent 是否存储在内存中
7. SharedPreferences
1.从PreferenceScreen 中 删除某个Preference
(1) . 先获取PreferenceScreen
PreferenceScreen ps = getPreferenceScreen();
(2). 获取要删除的Preference
Preference pf = findPreference(pfKey); // pfKey 为String类型3. 删除
if (pf != null && ps != null) {ps.removePreference(pf);
}
其中removePreference 会返回 boolean 值, 删除成功true, 否正false
从 PreferenceCategory 中删除Preference 也是类似,先要获取PreferenceCategory
2. Preference类图
(1) PreferenceGroup 是Preference 的子类,也是一个抽象类,可以拥有一个或者多个Preference, 类似View 和ViewGroup.
(2) PreferenceScreen 和PreferenceCategory 是PreferenceGroup的子类,扩展少量方法
(3) PreferenceScreen 作为xml 布局文件根标签时,其设置的Titile 是不会显示的(需要设置主题支持Actionbar类型的,才会显示)
PreferenceScreen 内部再嵌套一个PreferenceScreen时(组合), 内部的PreferenceScreen会显示Titile(点跳转后!!!), 但是其内部的Preference需要点击后才会显示出来
如:
<PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"<!--Title 不显示-->android:title="WiFi"android:key="first_preferencescreen"><CheckBoxPreferenceandroid:key="wifi enabled"android:title="WiFi" /><PreferenceScreenandroid:key="second_preferencescreen"<!--Title 显示-->android:title="WiFi settings"><!--内部Preference 不显示!!!! 需要点击进入后再显示Prefer wifi--><CheckBoxPreferenceandroid:key="prefer wifi"android:title="Prefer WiFi" /></PreferenceScreen>
</PreferenceScreen>
(4) 使用PreferenceCategory 可以显示标题, 并且Title这一行不能点击,因为PreferenceCategory内部覆写
public boolean isEnabled() {return false;
}
更多详细可以参考 https://blog.csdn.net/weixin_31767183/article/details/77748421
3. Activity&Fragment / Preference&Fragment 组合使用
其中,PreferenceFragmentCompat 可以自定义定制化的风格,作为父类提供一个app或者一个系统使用,使得风格统一。
(通过依赖库的方式编译进去,一样可以是androidx.preference的包名)
4. Actionbar (标题: 显示与隐藏 )
标题是否显示 与 它的主题 (Theme有关)
4.1 AppCompatActivity 默认有标题
/*** Support library version of {@link android.app.Activity#getActionBar}.** <p>Retrieve a reference to this activity's ActionBar.** @return The Activity's ActionBar, or null if it does not have one.*/@Nullablepublic ActionBar getSupportActionBar() {return getDelegate().getSupportActionBar();}
有两种方式隐藏标题
一种是在AndroidManifest 配置NoActionBar主题, 如 android:theme="@style/Theme.AppCompat.NoActionBar"
<activityandroid:name=".XXXXActivity"android:theme="@style/Theme.AppCompat.NoActionBar"><intent-filter><action android:name="android.intent.action.MAIN" /></intent-filter></activity>
另一种是在代码里配置, 如
getSupportActionBar().hide()
4.2 PreferenceActivity 默认没有标题
如果要显示标题, 在代码里配置主题 (可以引用android 库里的主题)
@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {if(Build.VERSION.SDK_INT> Build.VERSION_CODES.HONEYCOMB_MR2){this.setTheme(android.R.style.Theme_DeviceDefault);}
}
5. Preference 点击回调事件(onClick /OnPreferenceClickListener 、OnPreferenceChangeListener)
在 onBindViewHolder 的时候,设置 onClickListener, 这个listener 其实就是实现 View 的OnClickListener, Preference 内部交给performClick 处理。 详见后面
private final View.OnClickListener mClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {performClick(v);}};public void onBindViewHolder(PreferenceViewHolder holder) {View itemView = holder.itemView;Integer summaryTextColor = null;itemView.setOnClickListener(mClickListener);
提供点击监听的回调接口给客户端, 客户端可以决定是否响应事件 以及 在更新Preference 前进行设置操作(如设置Summary)
通过返回true 或者 false 告诉系统。 (例如 客户端在CheckBoxPreference中设置了监听, 实现了OnPreferenceChangeListener, 但是返回值为false, 则不会进行更新操作checked)
/*** Interface definition for a callback to be invoked when a {@link Preference} is* clicked.** @deprecated Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>* <a href="{@docRoot}reference/androidx/preference/package-summary.html">* Preference Library</a> for consistent behavior across all devices.* For more information on using the AndroidX Preference Library see* <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>.*/@Deprecatedpublic interface OnPreferenceClickListener {/*** Called when a Preference has been clicked.** @param preference The Preference that was clicked.* @return True if the click was handled.*/boolean onPreferenceClick(Preference preference);}
/*** Interface definition for a callback to be invoked when the value of this* {@link Preference} has been changed by the user and is* about to be set and/or persisted. This gives the client a chance* to prevent setting and/or persisting the value.** @deprecated Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>* <a href="{@docRoot}reference/androidx/preference/package-summary.html">* Preference Library</a> for consistent behavior across all devices.* For more information on using the AndroidX Preference Library see* <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>.*/@Deprecatedpublic interface OnPreferenceChangeListener {/*** Called when a Preference has been changed by the user. This is* called before the state of the Preference is about to be updated and* before the state is persisted.** @param preference The changed Preference.* @param newValue The new value of the Preference.* @return True to update the state of the Preference with the new value.*/boolean onPreferenceChange(Preference preference, Object newValue);}
performClick 里的逻辑, 如果有为Preference 设置intent ,则会调用startActivity 跳转
@RestrictTo(LIBRARY_GROUP_PREFIX)public void performClick() {if (!isEnabled() || !isSelectable()) {return;}onClick();if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {return;}PreferenceManager preferenceManager = getPreferenceManager();if (preferenceManager != null) {PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager.getOnPreferenceTreeClickListener();if (listener != null && listener.onPreferenceTreeClick(this)) {return;}}if (mIntent != null) {Context context = getContext();context.startActivity(mIntent);}}
6. persistent 是否存储在内存中(android:persistent="true")
<!-- Whether the Preference stores its value to the storage. --><attr name="persistent" />
<!-- Flag to control special persistent mode of an application. This shouldnot normally be used by applications; it requires that the system keepyour application running at all times. --><attr name="persistent" format="boolean" />
如果是false, 则退出Preference 后,再进入, 值不会保存。
6.1 CheckBoxPreference(TwoStatePreference)
在响应onClick 的时候,会回调(如果有注册监听), 并在setChecked的时候,调用persistXXX(例如 persistBoolean) 进行存储。
因此使用Preference 后, 会对其xml 定义的key值进行存储, 不需要手动调用SharePreference.edit.putXXX(key, value).apply 进行存储。
默认值可以用 android.defaultValue 设置, 会存储到Preference 对应的SharePreference中
//TwoStatePreference.java@Overrideprotected void onClick() {super.onClick();final boolean newValue = !isChecked();if (callChangeListener(newValue)) {setChecked(newValue);}}/*** Sets the checked state and saves it to the {@link SharedPreferences}.** @param checked The checked state.*/public void setChecked(boolean checked) {// Always persist/notify the first time; don't assume the field's default of false.final boolean changed = mChecked != checked;if (changed || !mCheckedSet) {mChecked = checked;mCheckedSet = true;persistBoolean(checked);if (changed) {notifyDependencyChange(shouldDisableDependents());notifyChanged();}}}
//Preference.java/*** Attempts to persist a boolean if this Preference is persistent.** @param value The value to persist.* @return True if this Preference is persistent. (This is not whether the* value was persisted, since we may not necessarily commit if there* will be a batch commit later.)* @see #persistString(String)* @see #getPersistedBoolean(boolean)*/protected boolean persistBoolean(boolean value) {if (!shouldPersist()) {return false;}if (value == getPersistedBoolean(!value)) {// It's already there, so the same as persistingreturn true;}PreferenceDataStore dataStore = getPreferenceDataStore();if (dataStore != null) {dataStore.putBoolean(mKey, value);} else {SharedPreferences.Editor editor = mPreferenceManager.getEditor();editor.putBoolean(mKey, value);tryCommit(editor);}return true;}
6.2 普通Preference 存储字符串
/*** Attempts to persist a String if this Preference is persistent.** @param value The value to persist.* @return True if this Preference is persistent. (This is not whether the* value was persisted, since we may not necessarily commit if there* will be a batch commit later.)* @see #getPersistedString(String)*/protected boolean persistString(String value) {if (!shouldPersist()) {return false;}// Shouldn't store nullif (TextUtils.equals(value, getPersistedString(null))) {// It's already there, so the same as persistingreturn true;}PreferenceDataStore dataStore = getPreferenceDataStore();if (dataStore != null) {dataStore.putString(mKey, value);} else {SharedPreferences.Editor editor = mPreferenceManager.getEditor();editor.putString(mKey, value);tryCommit(editor);}return true;}
读取存储的字符串
/*** Attempts to get a persisted String if this Preference is persistent.** @param defaultReturnValue The default value to return if either this* Preference is not persistent or this Preference is not present.* @return The value from the data store or the default return* value.* @see #persistString(String)*/protected String getPersistedString(String defaultReturnValue) {if (!shouldPersist()) {return defaultReturnValue;}PreferenceDataStore dataStore = getPreferenceDataStore();if (dataStore != null) {return dataStore.getString(mKey, defaultReturnValue);}return mPreferenceManager.getSharedPreferences().getString(mKey, defaultReturnValue);}
7. SharedPreferences
是一个接口???
根据同一个Context 获取到的SharePreference, 对命名相同key赋值或者读取时,实际是对同一个Key操作
public class ContextWrapper extends Context {@UnsupportedAppUsageContext mBase;//....@Overridepublic SharedPreferences getSharedPreferences(String name, int mode) {return mBase.getSharedPreferences(name, mode);}
}
8. 自定义Preference (如添加一个Preference 的属性值)
8.1 attrs.xml 添加自定义类型(declare-styleable)
其中,entryValue 为属性值, groupKey 则可以拓展为当前Preference 属于哪一个Group 组
<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="XXXPreference"><attr name="entryValue" format="string"></attr><attr name="groupKey" format="string"></attr></declare-styleable>
</resources>
8.2 获取自定义的属性值
通过TypedArray
public XXXPreference(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.XXXPreference, 0, 0);String key = getKey();if (key != null) {mKey = key;}mGroupKey = a.getText(R.styleable.RadioPreference_groupKey).toString();mValue = a.getText(R.styleable.RadioPreference_entryValue).toString();a.recycle();}
注意:XML 定义的Preference 的默认构造函数是
public XXXGroupPreference(Context context, AttributeSet attrs) {this(context, attrs, 0);setWidgetLayoutResource(R.layout.radiogroup);mContext = context;}
其中 radiogroup 为自定义的布局
8.3 XML 文件使用自定义Preference
其中app:entryValue 和 app:groupKey 即为自定义的属性 (xml文件的根标签 需要添加工具 xmlns:app="http://schemas.android.com/apk/res-auto")
<com.example.Test.XXXPreferenceandroid:key="@string/pref_test"android:defaultValue="false"android:persistent="true"app:entryValue="@string/val_test_value"app:groupKey="@string/pref_test_group"android:title="@string/title_test" />
这样,可以为Preference 新增一个属性,并且可以在XML 使用时赋值, 简单明了。
(也可以在定义一个数组,在代码中为各个Preference的自定义属性赋值)
Android Preference 笔记相关推荐
- android preference 启动activity,Android PreferenceActivity 学习笔记
在Ap中有时需要设置一些配置参数,这些参数通过配置文件保存. 为了设置这些参数,需要提供一个UI,针对这种需求,Android提供了preferenceActivity. PreferenceActi ...
- Android学习笔记之(一)开发环境搭建
Android学习笔记之(一)开发环境搭建 zouxy09@qq.com http://blog.csdn.net/zouxy09 至于说Android是什么之类的俺就不啰嗦了,因为它离我们太近了.直 ...
- Android开发笔记(七十三)代码混淆与反破解
代码混淆 ProGuard是ADT自带的apk混淆器,它的用途有: 1.压缩apk包的大小,能删除无用的代码,并简化部分类名和方法名. 2.加大破解源码的难度,因为部分类名和方法名被重命名,使得程序逻 ...
- Android学习笔记之AndroidManifest.xml文件解析(摘自皮狼的博客)
Android学习笔记之AndroidManifest.xml文件解析 一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它 ...
- Android开发笔记(一百零八)智能语音
智能语音技术 如今越来越多的app用到了语音播报功能,例如地图导航.天气预报.文字阅读.口语训练等等.语音技术主要分两块,一块是语音转文字,即语音识别:另一块是文字转语音,即语音合成. 对中文来说,和 ...
- Android进阶笔记:Messenger源码详解
Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...
- Android学习笔记21:ImageView获取网络图片
Android平台有3种网络接口可以使用,它们分别是:java.net.*(标准java接口).org.apache(Apache接口)和android.net.*(Android网络接口).本文将使 ...
- Android进阶笔记:AIDL内部实现详解 (二)
接着上一篇分析的aidl的流程解析.知道了aidl主要就是利用Ibinder来实现跨进程通信的.既然是通过对Binder各种方法的封装,那也可以不使用aidl自己通过Binder来实现跨进程通讯.那么 ...
- Android学习笔记(七):多个Activity和Intent
根据www.mars-droid.com:Andriod开发视频教学,先跳过书本<Beginning Android 2>的几个章,我是这两个资源一起看,需要进行一下同步.先初步了解一下应 ...
最新文章
- 一份超详细的数据科学路线图!
- IOS代码实现常用控件UIButton、UISlider、UISwitch、UISegmentedControl
- sublime 2 中常用快捷键
- Coursera吴恩达《神经网络与深度学习》课程笔记(4)-- 浅层神经网络
- JAVA开发环境及其开发
- What is the difference between a domain and web hosting? (域名和虚拟主机)
- JS字符转为json对象
- Linux SHELL 学习随笔--for 循环
- SAP License:发票校验抬头税码选择清单
- android sqlite联合,在联合查询中,Android SQLiteorder by 计算列_sql_开发99编程知识库...
- VMware 安装windows XP SP3 镜像下载地址 回忆xp经典
- Deep Ordinal Regression Network for Monocular Depth Estimation
- 一个屌丝程序猿的人生(五十)
- Low-poly低面建模(低像素多边形)
- 微信单删和互删有什么区别?
- Vue项目启动时 卡在98% after emitting StylelintWebpackPlugin无法运行
- 「详解」imgaug 图像增强方法
- c语言设计二极管图形,二极管的电路符号及图片识别
- aix 安装oracle smit install_latest,Oracle 9i在AIX5L系统上的详细安装过程
- k8s部署-39-pod有哪几种部署方式呢?能不能回滚版本呢?带你了解。