android preference-headers 属性,用Androidx的方式使用Preference-记一次官方文档错误

AndroidxPreference适配及遇到的问题
博主在将目标API提升到29时,发现PreferenceActivity中的部分方法已弃用,决定转向Androidx的Preference。在寻找解决方案过程中,遇到了二级设置无法打开的问题。通过查阅官方文档和自行尝试,博主解决了这个问题,包括用RecyclerView模拟header,处理点击事件,并创建自定义PreferenceFragment。然而在运行时出现错误,最终发现是官方文档中关于android:和app:属性的误导。修复后,博客指出官方文档可能存在错误。

用Androidx的方式使用Preference

起因

可能是因为targetApi=29的原因,在使用传统的PreferenceActivity的时候AS提醒我里面的一些方法已经被弃用,作为一个非常激进的业余菜鸟开发者,我的强迫症促使我去寻找其解决方案

近期收到我的小软件AndroCode有些用户反馈设置的第二级打不开,点击没有反应

找轮子

我开始百度找轮子,得知android10使用androidx全面替代,看了一下迁移的对应关系migrate,于是又百度androidx.preference,但结果寥寥无几,只有androidx PreferenceDialogFragmentCompat 和 DialogPreference的配合应用这一篇有一些记载,但对于我们这样的菜鸟很不友好,没有讲基础的使用方法或贴代码,里面的参考文档还被墙打不开。

不得已去看官方API,终于找到了使用方法指南,竟然有中文!!!还这么简洁,我大喜过望,赶紧上手操作

2c2d97b115768e6992892f860b246d3f.png

导入依赖

implementation 'androidx.preference:preference:1.1.0'

implementation 'androidx.core:core:1.2.0-beta01'

implementation 'androidx.fragment:fragment:1.2.0-rc01'

官方Demo

xmlns:app="http://schemas.android.com/apk/res-auto">

app:key="notifications"

app:title="Enable message notifications"/>

app:key="feedback"

app:title="Send feedback"

app:summary="Report technical issues or suggest new features"/>

public class MySettingsFragment extends PreferenceFragmentCompat {

@Override

public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

setPreferencesFromResource(R.xml.preferences, rootKey);

}

}

public class MySettingsActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

getSupportFragmentManager()

.beginTransaction()

.replace(R.id.settings_container, new MySettingsFragment())

.commit();

}

}

首先是没有了header的方式,但我的APP暂时还是需要这种布局,于是用RecyclerView模拟了一个

activity_settings_item.xml

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="?android:attr/selectableItemBackground"

android:clickable="true"

android:focusable="true"

android:orientation="vertical"

android:paddingStart="15dp"

android:paddingTop="10dp"

android:paddingEnd="15dp"

android:paddingBottom="10dp">

android:id="@+id/activity_settings_label"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:textAllCaps="true"

android:textStyle="bold"

android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

android:id="@+id/activity_settings_message"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:textAppearance="@style/TextAppearance.AppCompat.Small" />

activity_settings.xml

android:layout_width="match_parent"

android:id="@+id/activity_settings_layout"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/activity_settings_recyclerv"

android:layout_width="match_parent"

android:layout_height="match_parent" />

android:id="@+id/activity_settings_container"

android:layout_width="match_parent"

android:layout_height="match_parent" />

这里偷了个懒,用显示隐藏RecycerView的方式来给Fragment腾地方

由于PreferenceScreen还要用Fragment显示, 于是在AppCompatActivity中用recyclerview来触发事件显示fragment

onCreate:

headers.add(new SettingHeader("应用", "配置应用主题、会话", new SettingFragment(R.xml.settings_app)));

headers.add(new SettingHeader("编辑器", "配置编辑器、代码、保存", new SettingFragment(R.xml.settings_editor)));

headers.add(new SettingHeader("构建、运行", "配置工程构建和运行设置", new SettingFragment(R.xml.settings_build)));

headers.add(new SettingHeader("关于", "介绍等", new SettingFragment(R.xml.settings_about)));

recyclerv.setAdapter(new BaseRecyclerAdapter(headers) {

@Override

protected int getItemLayoutId(int viewType) {

return R.layout.activity_settings_item;

}

@Override

protected void bindData(@NonNull RecyclerViewHolder holder, int position, SettingHeader item) {

holder.getTextView(R.id.activity_settings_label).setText(item.label);

holder.getTextView(R.id.activity_settings_message).setText(item.message);

holder.itemView.setOnClickListener(v -> {

getSupportFragmentManager()

.beginTransaction()

.replace(R.id.activity_settings_container, item.fragmentCompat)

.commit();

recyclerv.setVisibility(View.GONE);

});

}

});

recyclerv.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));

为了减少代码,我机智地复用一个SettingFragment来加载不同xml

public static class SettingHeader {

public String label;

public String message;

public PreferenceFragmentCompat fragmentCompat;

public SettingHeader(String label, String message, PreferenceFragmentCompat fragmentCompat) {

this.label = label;

this.message = message;

this.fragmentCompat = fragmentCompat;

}

}

public static class SettingFragment extends PreferenceFragmentCompat {

private final int id;

public SettingFragment(int xmlId) {

super();

this.id = xmlId;

}

@Override

public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

setPreferencesFromResource(id, rootKey);

}

@Override

public void onDisplayPreferenceDialog(Preference preference) {

if (preference instanceof GenKeystorePreference) {

((GenKeystorePreference) preference).showDialog();

} else

super.onDisplayPreferenceDialog(preference);

}

}

于是我满怀信心地用AS跑了起来,一起看起来是那么地完美

952f9cc675c5961bd667b30f4834a056.png

没问题,打开应用item

f37818bc9583cef7d9ba9171db1686ce.png

???这是什么鬼

e8b29804ac0ce349e6d128ecb2903321.png

寻找错误原因

因为用到了一个换肤框架,有些兼容问题,起初我以为是字体颜色和背景一样,于是开始捣鼓主题,禁用框架,但毫无结果

终于,机缘巧合之下,log提示我自定义的Preference有问题,DialogPreference不再提供默认的新建Dialog操作,要通过onDisplayPreferenceDialog来设置,将其修复后log提示我没有Preference have no Key!

但我明明有定义,完全是按照官方的教程来的啊!思考半天,我尝试用android:替换app:,最后运行如下

1cfe04dea63f66b1399288f043fc2bbb.png

e8b29804ac0ce349e6d128ecb2903321.png

官方文档有错!本人记下了!!!

看这架势应该是支持icon,预留了一个ImageView

结论

官方文档有错,还是用android:而不是app:,估计是升级lib忘了同步还是写错了?

d 1 other context) [ 99% 8464/8503] //packages/apps/Settings:Settings-core javac [common] FAILED: out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/Settings-core.jar rm -rf "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/classes" "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/anno" "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/srcjars" "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/Settings-core.jar" && mkdir -p "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/classes" "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/anno" "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/srcjars" && out/host/linux-x86/bin/zipsync -d out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/srcjars -l out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/srcjars/list -f "*.java" out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/gen/android/R.srcjar out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/kapt/kapt-sources.jar && (if [ -s out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/srcjars/list ] || [ -s out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/Settings-core.jar.rsp ] ; then out/host/linux-x86/bin/soong_javac_wrapper prebuilts/jdk/jdk11/linux-x86/bin/javac -J-Xmx2048M -J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -Xmaxerrs 9999999 -encoding UTF-8 -sourcepath "" -g -XDskipDuplicateBridges=true -XDstringConcat=inline -proc:none -Xlint:-dep-ann --system=out/soong/.intermediates/build/soong/java/core-libraries/legacy-core-platform-api-stubs-system-modules/android_common/system -classpath out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/kotlin_headers/Settings-core.jar:out/soong/.intermediates/frameworks/base/ext/android_common/turbine-combined/ext.jar:out/soong/.intermediates/frameworks/base/framework/android_common/turbine-combined/framework.jar:out/soong/.intermediates/frameworks/opt/telephony/telephony-common/android_common/turbine-jarjar/telephony-common.jar:out/soong/.intermediates/frameworks/opt/net/ims/ims-common/android_common/turbine-jarjar/ims-common.jar:out/soong/.intermediates/frameworks/base/packages/SettingsLib/search/SettingsLib-search/android_common/turbine-combined/SettingsLib-search.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.annotation_annotation/android_common/turbine-combined/androidx.annotation_annotation.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.lifecycle_lifecycle-common/android_common/turbine-combined/androidx.lifecycle_lifecycle-common.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx-legacy/androidx.legacy_legacy-support-v4/android_common/turbine-combined/androidx.legacy_legacy-support-v4.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.lifecycle_lifecycle-runtime/android_common/turbine-combined/androidx.lifecycle_lifecycle-runtime.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.recyclerview_recyclerview/android_common/turbine-combined/androidx.recyclerview_recyclerview.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.preference_preference/android_common/turbine-combined/androidx.preference_preference.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat/android_common/turbine-combined/androidx.appcompat_appcompat.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx-legacy/androidx.legacy_legacy-preference-v14/android_common/turbine-combined/androidx.legacy_legacy-preference-v14.jar:out/soong/.intermediates/frameworks/base/packages/SettingsLib/SettingsLib/android_common/turbine-combined/SettingsLib.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx-constraintlayout_constraintlayout/android_common/turbine-combined/androidx-constraintlayout_constraintlayout.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.slice_slice-builders/android_common/turbine-combined/androidx.slice_slice-builders.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.slice_slice-core/android_common/turbine-combined/androidx.slice_slice-core.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.slice_slice-view/android_common/turbine-combined/androidx.slice_slice-view.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.core_core/android_common/turbine-combined/androidx.core_core.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat/android_common/turbine-combined/androidx.appcompat_appcompat.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.cardview_cardview/android_common/turbine-combined/androidx.cardview_cardview.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.preference_preference/android_common/turbine-combined/androidx.preference_preference.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.recyclerview_recyclerview/android_common/turbine-combined/androidx.recyclerview_recyclerview.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.window_window/android_common/turbine-combined/androidx.window_window.jar:out/soong/.intermediates/prebuilts/sdk/current/extras/material-design-x/com.google.android.material_material/android_common/turbine-combined/com.google.android.material_material.jar:out/soong/.intermediates/external/setupcompat/setupcompat/android_common/turbine-combined/setupcompat.jar:out/soong/.intermediates/external/setupdesign/setupdesign/android_common/turbine-combined/setupdesign.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.lifecycle_lifecycle-runtime/android_common/turbine-combined/androidx.lifecycle_lifecycle-runtime.jar:out/soong/.intermediates/prebuilts/sdk/current/androidx-legacy/androidx.lifecycle_lifecycle-extensions/android_common/turbine-combined/androidx.lifecycle_lifecycle-extensions.jar:out/soong/.intermediates/external/guava/guava/android_common/turbine-combined/guava.jar:out/soong/.intermediates/external/jsr305/jsr305/android_common/turbine-combined/jsr305.jar:out/soong/.intermediates/frameworks/libs/net/common/net-utils-framework-common/android_common/turbine-jarjar/net-utils-framework-common.jar:out/soong/.intermediates/packages/apps/Settings/protos/settings-contextual-card-protos-lite/android_common/turbine-combined/settings-contextual-card-protos-lite.jar:out/soong/.intermediates/packages/apps/Settings/protos/settings-log-bridge-protos-lite/android_common/turbine-combined/settings-log-bridge-protos-lite.jar:out/soong/.intermediates/packages/apps/Settings/protos/settings-telephony-protos-lite/android_common/turbine-combined/settings-telephony-protos-lite.jar:out/soong/.intermediates/packages/apps/Settings/contextualcards/android_common/aar/classes-combined.jar:out/soong/.intermediates/packages/apps/Settings/settings-logtags/android_common/turbine-combined/settings-logtags.jar:out/soong/.intermediates/packages/apps/Settings/statslog-settings/android_common/turbine-combined/statslog-settings.jar:out/soong/.intermediates/external/zxing/core/zxing-core-1.7/android_common/combined/zxing-core-1.7.jar:out/soong/.intermediates/hardware/interfaces/dumpstate/1.0/android.hardware.dumpstate-V1.0-java/android_common/turbine-combined/android.hardware.dumpstate-V1.0-java.jar:out/soong/.intermediates/hardware/interfaces/dumpstate/1.1/android.hardware.dumpstate-V1.1-java/android_common/turbine-combined/android.hardware.dumpstate-V1.1-java.jar:out/soong/.intermediates/hardware/interfaces/dumpstate/aidl/android.hardware.dumpstate-V1-java/android_common/turbine-combined/android.hardware.dumpstate-V1-java.jar:out/soong/.intermediates/external/lottie/lottie/android_common/turbine-combined/lottie.jar:out/soong/.intermediates/frameworks/opt/net/wifi/libs/WifiTrackerLib/WifiTrackerLib/android_common/turbine-combined/WifiTrackerLib.jar:out/soong/.intermediates/frameworks/base/packages/SettingsLib/ActivityEmbedding/SettingsLibActivityEmbedding/android_common/turbine-combined/SettingsLibActivityEmbedding.jar:out/soong/.intermediates/packages/apps/Settings/Settings-change-ids/android_common/turbine-combined/Settings-change-ids.jar:out/soong/.intermediates/frameworks/base/packages/SystemUI/unfold/SystemUIUnfoldLib/android_common/turbine-combined/SystemUIUnfoldLib.jar:out/soong/.intermediates/external/kotlinc/kotlin-stdlib/android_common/combined/kotlin-stdlib.jar:out/soong/.intermediates/external/kotlinc/kotlin-stdlib-jdk7/android_common/combined/kotlin-stdlib-jdk7.jar:out/soong/.intermediates/external/kotlinc/kotlin-stdlib-jdk8/android_common/combined/kotlin-stdlib-jdk8.jar:out/soong/.intermediates/external/kotlinc/kotlin-annotations/android_common/combined/kotlin-annotations.jar -source 11 -target 11 -d out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/classes -s out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/anno @out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/Settings-core.jar.rsp @out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/srcjars/list ; fi ) && out/host/linux-x86/bin/soong_zip -jar -o out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/Settings-core.jar -C out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/classes -D out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/classes && rm -rf "out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/javac/srcjars" packages/apps/Settings/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java:55: error: cannot find symbol .isEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION); ^ symbol: variable SETTINGS_APP_LANGUAGE_SELECTION location: class FeatureFlagUtils 1 error [ 99% 8466/8503] //frameworks/base/packages/SystemUI:SystemUI r8 [common] Warning: Missing class android.compat.annotation.UnsupportedAppUsage (referenced from: void com.android.systemui.people.widget.PeopleBackupHelper.writeNewStateDescription(android.os.ParcelFileDescriptor)) 03:15:40 ninja failed with: exit status 1 #### failed to build some targets (05:10 (mm:ss)) #### Build android failed! 看下什么错误
最新发布
11-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值