zoukankan      html  css  js  c++  java
  • Android9.0 Settings 修改踩坑记录

    问题现象

    M3eYfs.png

    上图展示的很清楚,当系统语言为中文时,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,又找到如下的地方

    M3YOit.png

    看着 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

    M3Ui80.png

    这就很诡异了,感觉此路不通啊,那好吧,乖乖去捋一捋源码吧

    经过简单的分析,找到 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

    M3aRmD.png

    https://segmentfault.com/a/1190000020956652

    对比 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-builders 
        android-slices-core 
        android-slices-view 
        android-support-compat 
        android-support-v4 
        android-support-v13 
        android-support-v7-appcompat 
        android-support-v7-cardview 
        android-support-v7-preference 
        android-support-v7-recyclerview 
        android-support-v14-preference 
    

    android-support-v7-preference 导入静态库,而源码中并没有对应的目录,已经替代为 androidx,悲催了,这下想改资源文件解决bug看来是不行了。

    看了下 Android10.0 下 Settings 的 mk,发现已经全部替换为 androidx

    Android.mk

    
    LOCAL_STATIC_ANDROID_LIBRARIES := 
        androidx-constraintlayout_constraintlayout 
        androidx.slice_slice-builders 
        androidx.slice_slice-core 
        androidx.slice_slice-view 
        androidx.core_core 
        androidx.appcompat_appcompat 
        androidx.cardview_cardview 
        androidx.preference_preference 
        androidx.recyclerview_recyclerview 
        com.google.android.material_material 
        setupcompat 
        setupdesign
    
    

    解决办法

    通过进一步分析,找到一个关键字段 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);
        }
    
    
  • 相关阅读:
    js的继承实现方式
    jdbc调用通用存储过程完成分页
    最近在忙些什么......
    【转】说服下属的“攻心术”
    设计模式原则详解
    【转】职场学做“功夫熊猫”
    内核初始化优化宏 ,初始化顺序, __init,__devexit等
    Linux 嵌入式启动以及优化
    每个程序员都该知道的10大编程格言
    linux 用户空间 和 内核空间 延时函数
  • 原文地址:https://www.cnblogs.com/cczheng-666/p/12092838.html
Copyright © 2011-2022 走看看