仓廪实则知礼节,衣食足则知荣辱。这篇文章主要讲述Android9.0 Settings 修改踩坑记录相关的知识,希望能为你提供帮助。
问题现象
文章图片
上图展示的很清楚,当系统语言为中文时,PreferenceScreen 中的折叠项 summary 描述重复显示的 bug,系统语言为英文时正常。
修改历程先搜索 当前显示了 字符串,还真找到了
prebuiltssdkcurrentsupportv7preference esvalues-zh-rCNvalues-zh-rCN.xml
<
?xml version="
1.0"
encoding="
utf-8"
?>
<
resources xmlns:ns1="
urn:oasis:names:tc:xliff:document:1.2"
>
<
string msgid="
3265458434114353660"
name="
expand_button_title"
>
"
高级"
<
/string>
<
string msgid="
5255557321652385027"
name="
summary_collapsed_preference_list"
>
"
当前显示了 <
ns1:g id="
CURRENT_ITEMS"
>
%1$s<
/ns1:g>
项(已添加 <
ns1:g id="
ADDED_ITEMS"
>
%2$s<
/ns1:g>
项)"
<
/string>
<
string msgid="
2082379519172883894"
name="
v7_preference_off"
>
"
关闭"
<
/string>
<
string msgid="
7922757586228621900"
name="
v7_preference_on"
>
"
开启"
<
/string>
<
/resources>
再接着搜索 summary_collapsed_preference_list,又找到如下的地方
文章图片
看着 androidTest 相关的可以忽略,直接看 CollapsiblePreferenceGroupController.java
frameworkssupportpreferencesrcmainjavaandroidxpreferenceCollapsiblePreferenceGroupController.java
private void setSummary(List<
Preference>
collapsedPreferences) {
CharSequence summary = null;
final List<
PreferenceGroup>
parents = new ArrayList<
>
();
for (Preference preference : collapsedPreferences) {
final CharSequence title = preference.getTitle();
if (preference instanceof PreferenceGroup &
&
!TextUtils.isEmpty(title)) {
parents.add((PreferenceGroup) preference);
}
if (parents.contains(preference.getParent())) {
if (preference instanceof PreferenceGroup) {
parents.add((PreferenceGroup) preference);
}
continue;
}
if (!TextUtils.isEmpty(title)) {
if (summary == null) {
summary = title;
} else {
summary = getContext().getString(
R.string.summary_collapsed_preference_list, summary, title);
}
}
}
setSummary(summary);
}
哈,这下证实了 bug 的由来,summary_collapsed_preference_list 字符串经过格式化 for 循环的叠加自然会出现 当前显示了 当前显示了 当前显示了....
那就简单了,把 summary_collapsed_preference_list 对应的中文字符串修改了就行呗,但是事情没有那么简单,经过修改重新编译测试 bug 依旧,然后又继续搜索,
在 out 目录下还发现了另一个 当前显示了 字符串,文件内容和 prebuilts 下的是一模一样的,但是文件时间却是 2018-05-25 06:04
文章图片
这就很诡异了,感觉此路不通啊,那好吧,乖乖去捋一捋源码吧
经过简单的分析,找到 Settings 中的 HighlightablePreferenceGroupAdapter 类
vendormediatekproprietarypackagesappsMtkSettingssrccomandroidsettingswidgetHighlightablePreferenceGroupAdapter.java
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceGroupAdapter;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.PreferenceViewHolder;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
public class HighlightablePreferenceGroupAdapter extends PreferenceGroupAdapter {
可以看到继承的是 PreferenceGroupAdapter,而且还是 v7 包下面的,继续搜索 PreferenceGroupAdapter.java
文章图片
https://segmentfault.com/a/1190000020956652
【Android9.0 Settings 修改踩坑记录】对比 8.1 和 9.0 一看,9.0 已经没有 v7 包支持了,而是改用 androidx 替代,具体介绍可看 Preference组件探究之Base,Support及AndroidX对比
难怪我们上面修改 summary_collapsed_preference_list 没用,上面调用的类 CollapsiblePreferenceGroupController 也是在 androidx 包下,查看 Settings 下的 mk
LOCAL_STATIC_ANDROID_LIBRARIES :=android-slices-buildersandroid-slices-coreandroid-slices-viewandroid-support-compatandroid-support-v4android-support-v13android-support-v7-appcompatandroid-support-v7-cardviewandroid-support-v7-preferenceandroid-support-v7-recyclerviewandroid-support-v14-preference
android-support-v7-preference 导入静态库,而源码中并没有对应的目录,已经替代为 androidx,悲催了,这下想改资源文件解决bug看来是不行了。
看了下 Android10.0 下 Settings 的 mk,发现已经全部替换为 androidx
Android.mk
LOCAL_STATIC_ANDROID_LIBRARIES :=androidx-constraintlayout_constraintlayoutandroidx.slice_slice-buildersandroidx.slice_slice-coreandroidx.slice_slice-viewandroidx.core_coreandroidx.appcompat_appcompatandroidx.cardview_cardviewandroidx.preference_preferenceandroidx.recyclerview_recyclerviewcom.google.android.material_materialsetupcompatsetupdesign
解决办法通过进一步分析,找到一个关键字段 initialExpandedChildrenCount
vendormediatekproprietarypackagesappsMtkSettings esxml etwork_and_internet.xml
<
PreferenceScreen
xmlns:android="
http://schemas.android.com/apk/res/android"
xmlns:settings="
http://schemas.android.com/apk/res-auto"
android:key="
network_and_internet_screen"
android:title="
@string/network_dashboard_title"
settings:initialExpandedChildrenCount="
5"
>
该字段在 PreferenceGroup 中获取并赋值,用来区分当前 Preference 要显示的数量,剩余的需要折叠显示
frameworkssupportpreferencesrcmainjavaandroidxpreferencePreferenceGroup.java
public PreferenceGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mPreferenceList = new ArrayList<
>
();
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.PreferenceGroup, defStyleAttr, defStyleRes);
mOrderingAsAdded =
TypedArrayUtils.getBoolean(a, R.styleable.PreferenceGroup_orderingFromXml,
R.styleable.PreferenceGroup_orderingFromXml, true);
if (a.hasValue(R.styleable.PreferenceGroup_initialExpandedChildrenCount)) {
setInitialExpandedChildrenCount((TypedArrayUtils.getInt(
a, R.styleable.PreferenceGroup_initialExpandedChildrenCount,
R.styleable.PreferenceGroup_initialExpandedChildrenCount, Integer.MAX_VALUE)));
}
a.recycle();
}
最终在 CollapsiblePreferenceGroupController 中读取该字段,判断是否需要添加 ExpandButton 即高级折叠下拉按钮
所以我们只需要将 initialExpandedChildrenCount 设置成最大即可,Preference 将不再折叠,当然这是一种偷懒的做法,这样会失去原来的用户体验
vendormediatekproprietarypackagesappsMtkSettingssrccomandroidsettingswidgetHighlightablePreferenceGroupAdapter.java
/**
* Tries to override initial expanded child count.
* <
p/>
* Initial expanded child count will be ignored if:
* 1. fragment contains request to highlight a particular row.
* 2. count value is invalid.
*/
public static void adjustInitialExpandedChildCount(SettingsPreferenceFragment host) {
Log.e("
HighlightablePreferenceGroupAdapter"
,"
adjustInitialExpandedChildCount()"
);
if (host == null) {
return;
}
final PreferenceScreen screen = host.getPreferenceScreen();
if (screen == null) {
return;
}
final Bundle arguments = host.getArguments();
if (arguments != null) {
final String highlightKey = arguments.getString(EXTRA_FRAGMENT_ARG_KEY);
if (!TextUtils.isEmpty(highlightKey)) {
// Has highlight row - expand everything
screen.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
return;
}
}final int initialCount = host.getInitialExpandedChildCount();
//cczheng add for expand everything preference S
Log.e("
HighlightablePreferenceGroupAdapter"
,"
initialCount="
+initialCount);
if (true) {
screen.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
return;
}
//E
if (initialCount <
= 0) {
return;
}
screen.setInitialExpandedChildrenCount(initialCount);
}
推荐阅读
- Android signalR
- springboot 微信支付里的app支付坑注意,requestPayment,支付报错,"errMsg":"requestPayment:fail:[payment微
- react app相关知识
- 微信中域名被封-页面添加遮罩层提示用户使用浏览器打开(或下载APP)
- create-react-app兼容ie9配置
- Spring Boot中配置文件application.properties里面配置项的引用
- 浅谈Mybatis通用Mapper使用方法_java - JAVA
- application.properties和application.yml文件的区别
- ClassPathXmlApplicationContext源码分析