android-preferences 相关问题

为什么使用AndroidX时嵌套的PreferenceScreen打不开?

我正在使用 AndroidX 的首选项库来管理我的应用程序的设置。我的 SettingsFragment 派生自 PreferenceFragmentCompat 并加载以下布局: 我正在使用 AndroidX 的首选项库来管理我的应用程序的设置。我的 SettingsFragment 源自 PreferenceFragmentCompat 并加载以下布局: <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <androidx.preference.PreferenceScreen android:key="screen_backup_key" android:title="@string/local_database"> <androidx.preference.Preference android:key="button_save_key" android:title="@string/export" /> <androidx.preference.Preference android:key="button_load_key" android:title="@string/_import" /> </androidx.preference.PreferenceScreen> <androidx.preference.Preference android:key="screen_about" android:title="@string/about" /> </androidx.preference.PreferenceScreen> 布局显示正确,但是当我单击嵌套的 PreferenceScreen 条目时,没有任何反应。它以前可以与 支持库 中的 PreferenceScreen 一起使用,但现已弃用。 我希望看到这个嵌套的内容PreferenceScreen。我做错了什么? AndroidX 的首选项库不再支持它。 使用 a 声明同一 XML 资源中的嵌套层次结构 不再支持嵌套 PreferenceScreen。你应该使用 而是嵌套的 Fragment 对象。 每个单独的屏幕都需要一个单独的 PreferenceFragmentCompat。 如果您有大量偏好或不同类别,您 可以将它们显示在单独的屏幕上。每个屏幕应该是一个 PreferenceFragmentCompat 有自己独立的层次结构。优先 然后,您的初始屏幕上可以链接到包含以下内容的子屏幕: 相关首选项。 你这样做: 要将屏幕与首选项链接,您可以在中声明 app:fragment XML,或者您可以使用 Preference.setFragment()。设置完整包 启动时应启动的 PreferenceFragmentCompat 的名称 点击Preference,如下图: <Preference app:fragment="com.example.SyncFragment" .../> 这是进一步阅读的来源。 嵌套 ScreenPreference 无法在 AndroidX 中开箱即用。下面是一个处理嵌套 ScreenPreference 的 PreferenceActivity 替换示例。类似的方法可以仅用于片段。 注意以下事项: 活动布局没有利用大屏幕或可折叠设备。 片段不会持续存在(因此,如果屏幕旋转,它将返回到第一个首选项片段)。 只能调用一次addPreferencesFromResource()。 以下是如何使用它来替换 PreferenceActivity 作为基类: 将 PreferenceActivity 替换为 PreferenceActivityEx。 将 AppCompatActivity 兼容主题添加到 AndroidManifest.xml 中的继承 Activity。例如:android:theme="@style/Theme.AppCompat"。 将任何 androidx.preference 导入替换为 androidx.preference。 将 addPreferencesFromResource() 方法中的 onCreate() 调用之后处理首选项的代码移至新的覆盖 onPreferencesCreated() 方法。 activity_preference_ex.xml: <?xml version="1.0" encoding="utf-8"?> <androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/preferences_container" android:layout_width="match_parent" android:layout_height="match_parent" /> PreferenceActivityEx.java: import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; public class PreferenceActivityEx extends AppCompatActivity { private RootPreferenceFragmentCompatEx mPreferencesFragment; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_preference_ex); } @Override protected void onResume() { super.onResume(); if (mPreferencesFragment == null) throw new IllegalStateException("Must call 'addPreferencesFromResource()' in the 'onCreate()' method."); } protected Preference findPreference(@NonNull CharSequence key) { if (mPreferencesFragment == null) throw new IllegalStateException("Must call 'addPreferencesFromResource()' before 'findPreference()'"); return mPreferencesFragment.findPreference(key); } protected PreferenceScreen getPreferenceScreen() { if (mPreferencesFragment == null) throw new IllegalStateException("Must call 'addPreferencesFromResource()' before 'getPreferenceScreen()'"); return mPreferencesFragment.getPreferenceScreen(); } protected void onPreferencesCreated() { } protected void addPreferencesFromResource(int preferencesResId) { if (mPreferencesFragment != null) throw new IllegalStateException("Only a single call to addPreferencesFromResource() is allowed."); mPreferencesFragment = new RootPreferenceFragmentCompatEx(preferencesResId); mPreferencesFragment.setOnPreferencesCreatedListener(this::onPreferencesCreated); getSupportFragmentManager().beginTransaction() .replace(R.id.preferences_container, mPreferencesFragment) .commit(); } public static abstract class PreferenceFragmentCompatEx extends PreferenceFragmentCompat { @Override public boolean onPreferenceTreeClick(@NonNull Preference preference) { if (preference instanceof PreferenceScreen) { PreferenceScreen preferenceScreen = (PreferenceScreen) preference; // Create a new fragment to display the nested PreferenceScreen NodePreferenceFragmentCompatEx fragment = new NodePreferenceFragmentCompatEx(preferenceScreen); // Use the FragmentManager to replace the current fragment with the nested one getParentFragmentManager().beginTransaction() .replace(getId(), fragment) .addToBackStack(null) .commit(); return true; } return super.onPreferenceTreeClick(preference); } } public static class NodePreferenceFragmentCompatEx extends PreferenceFragmentCompatEx { private PreferenceScreen mPreferenceScreen; public NodePreferenceFragmentCompatEx() { } public NodePreferenceFragmentCompatEx(PreferenceScreen preferenceScreen) { mPreferenceScreen = preferenceScreen; } @Override public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { if (mPreferenceScreen != null) setPreferenceScreen(mPreferenceScreen); } } public static class RootPreferenceFragmentCompatEx extends PreferenceFragmentCompatEx { private int mPreferencesResId; private OnPreferencesCreatedListener mOnPreferencesCreatedListener; public RootPreferenceFragmentCompatEx() { } public RootPreferenceFragmentCompatEx(int preferencesResId) { mPreferencesResId = preferencesResId; } private void setOnPreferencesCreatedListener(OnPreferencesCreatedListener onPreferencesCreatedListener) { mOnPreferencesCreatedListener = onPreferencesCreatedListener; } @Override public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { if (mPreferencesResId != 0) { setPreferencesFromResource(mPreferencesResId, rootKey); if (mOnPreferencesCreatedListener != null) mOnPreferencesCreatedListener.onPreferencesCreated(); } } } private interface OnPreferencesCreatedListener { void onPreferencesCreated(); } }

回答 2 投票 0

如何在 Espresso 中模拟 Jetpack 数据存储

我从 SharedPreferences 切换到 Jetpack DataStore。 我无法在仪器测试中模拟来自数据存储调用的数据 声明中 val dataStore = context.createDataStore(名称...

回答 1 投票 0

动态更改android首选项的widgetlayout资源

我在首选项屏幕内创建了一个首选项条目,如下所示: 我在首选项屏幕内创建了一个首选项条目,如下所示: <PreferenceScreen> <Preference android:title="title" android:key="key" android:widgetLayout="@layout/someview"/> </PreferenceScreen> 这里我设置了一个 widgetlayout 资源,它应该显示在首选项的右侧(就像复选框首选项的复选框)。我还可以在我的 PreferenceActivity.onCreate() 代码中设置此资源,如下所示: Preference myPreference = findPreference("key"); myPreference.setWidgetLayoutResource(R.layout.someview); 两种方法都可以正常工作,因此我可以在首选项右侧看到我的资源。 但是,我无法访问此资源(someview)以在运行时更改其属性。 手动设置资源 ID、从资源中夸大它或findViewById似乎都不起作用 - 我有无效的资源/资源 ID 未找到异常。似乎偏好活动稍后会导致资源膨胀。 有人遇到同样的问题吗?关于如何在运行时更改 widgetlayout 资源属性有什么想法吗? 这里有一个类似的问题,但没有回答 [android-开发者] 在首选项 widgetLayout 中访问小部件时出现问题 我似乎也有同样的问题,我尝试了这样的方法: 1) 创建自定义 Preference 并覆盖 onBindView(): public class ProgressBarPreference extends Preference { private ProgressBar mProgressBar; // constructors @Override protected void onBindView(View view) { super.onBindView(view); mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar); } public ProgressBar getProgressBar() { return mProgressBar; } } 2) 将此首选项添加到屏幕 xml: <package.ProgressBarPreference android:key="key" android:summary="summary" android:title="title" android:widgetLayout="@layout/preference_widget_progressbar" /> preference_widget_progressbar.xml <?xml version="1.0" encoding="utf-8"?> <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/progressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> 或致电setWidgetLayoutResource()。 3) 当onPreferenceTreeClick():时获取ProgressBar if (preference instanceof ProgressBarPreference) { ProgressBar progressBar = ((ProgressBarPreference) preference).getProgressBar(); // TODO something } 然而,已经一年多了! 我对 joinAero 的情况有部分解决方法。如果目标只是在小部件中显示或隐藏不确定的进度条,则技巧是在代码中设置和清除小部件布局资源。 1) 定义包含 ProgressBar 的小部件布局。无需分配 ID。首选项_widget_progressbar.xml: <?xml version="1.0" encoding="utf-8"?> <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> 2)不要在settings.xml中指定小部件 <package.ProgressBarPreference android:key="key" android:summary="summary" android:title="title" /> 3)当你想显示进度条时,将widget资源设置为preference_widget_progressbar。要清除它,请将其设置为 0。需要调用 notifyChanged() 来更新屏幕。 public void showProgressBar(boolean isVisible) { // Show or hide the entire widget (which contains only a ProgressBar) setWidgetLayoutResource(isVisible ? R.layout.preference_widget_progressbar: 0); notifyChanged(); // Update screen } 获取指向实际 ProgressBar 的指针非常困难,特别是当首选项位于库项目中时。我按照这篇文章使用getIdentifier()取得了一些成功,但这种方法实际上隐藏了整个小部件,而在进度条上设置可见性则留下了一个空白的小部件可见。 这里有一个解决方法: 创建小部件布局并设置 onClick 属性, <?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/icon" android:layout_width="48dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:background="?android:attr/selectableItemBackground" *android:onClick="onMyKeyClicked"* android:scaleType="centerInside" android:src="@drawable/ic_action_info" /> 然后在您的首选项中设置小部件布局, <ListPreference android:defaultValue="1" android:entries="@array/my_entries" android:entryValues="@array/my_values" android:key="my_key" android:title="@string/pref_my_key_title" android:widgetLayout="@layout/pref_layout_my_key" /> 然后在你的活动中有一个类似的方法, public void onMyKeyClicked(View v) { Toast.makeText(this, "My key widget clicked", Toast.LENGTH_SHORT).show(); } 因此,对于带有小部件的每个首选项,您都会有一个将 onClick 属性设置为活动中唯一方法的布局。你觉得怎么样? 我找到了解决此问题的方法,而无需创建自定义首选项。 此解决方案的一个好处是,您可以将相同的小部件资源与不同的侦听器实现(即“setOnClickListener”)一起使用。 下面的示例创建了两个 EditTextPreferecnes,每个都指向相同的小部件布局。然后使用 addOnChildAttachStateChangeListener 根据需要设置小部件。需要侦听器是因为首选项 Recycler 视图中首选项的视图绑定是最后发生的事情之一或 onResume() 之后发生的事情之一。 此外,请确保使用非零 ID。 琴弦: <resources> <!-- Preference Titles --> <string name="prefs_header">Prefs With Widgets</string> <!-- Preferences --> <string name="pref_key_a">pref_key_a</string> <string name="pref_key_b">pref_key_b</string> </resources> 小部件布局: <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageButton android:id="@+id/imageButton" style="@android:style/Widget.Holo.ImageButton" android:layout_width="32dp" android:layout_height="32dp" android:contentDescription="@string/messages_header" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@android:drawable/stat_sys_download" /> </androidx.constraintlayout.widget.ConstraintLayout> 首选布局: <PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"> <PreferenceCategory app:iconSpaceReserved="false" app:title="Prefs With Widgets"> <EditTextPreference app:iconSpaceReserved="false" app:key="@string/pref_key_a" app:title="Test Button A" app:useSimpleSummaryProvider="true" app:widgetLayout="@layout/my_widget" /> <EditTextPreference app:iconSpaceReserved="false" app:key="@string/pref_key_b" app:title="Test Button B" app:useSimpleSummaryProvider="true" app:widgetLayout="@layout/my_widget" /> </PreferenceCategory> </PreferenceScreen> 科特林: class SettingsFragment : PreferenceFragmentCompat() { private lateinit var _onChildAttachListener : RecyclerView.OnChildAttachStateChangeListener private lateinit var _editTextA : EditTextPreference private lateinit var _editTextB : EditTextPreference override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) _editTextA = preferenceScreen.findPreference(getString(R.string.pref_key_a))!! _editTextB = preferenceScreen.findPreference(getString(R.string.pref_key_b))!! _editTextA.setViewId(PREF_A_ID) _editTextB.setViewId(PREF_B_ID) _onChildAttachListener = object : RecyclerView.OnChildAttachStateChangeListener { override fun onChildViewAttachedToWindow(view: View) { if(PREF_A_ID == view.id){ view.findViewById<ImageButton>(R.id.imageButton).setOnClickListener { Toast.makeText(context, "Button A", Toast.LENGTH_SHORT).show() } } if(PREF_B_ID == view.id){ view.findViewById<ImageButton>(R.id.imageButton).setOnClickListener { Toast.makeText(context, "Button B", Toast.LENGTH_SHORT).show() } } } override fun onChildViewDetachedFromWindow(view: View) { // Do nothing.. } } } override fun onResume() { listView.addOnChildAttachStateChangeListener(_onChildAttachListener) super.onResume() } override fun onDestroy() { listView.removeOnChildAttachStateChangeListener(_onChildAttachListener) super.onDestroy() } companion object { // Note: Set ID's to anything but 0 const val PREF_A_ID = 1 const val PREF_B_ID = 2 } }

回答 4 投票 0

Android:SharedPreference:启动时未设置默认值

我的应用程序中有列表首选项。它们似乎没有在安装后立即设置为默认值 - 它们似乎为空。我试图找出为什么我的默认首选项不是...

回答 4 投票 0

如何替换 setTargetFragment() 既然它已被弃用

setTargetFragment() 在 Java 中已被弃用,我不明白它的正确替代品,因为 android 文档使用它并且已经过时了。我相信 FragmentManager 是正确的替代品...

回答 3 投票 0

如何将图标添加到 android:drawable 文件夹中?

我将图标放在preferences.xml 文件中的选项旁边。我正在寻找一些图标来代表我拥有的特定选项,但找不到它们。所以我想知道如何添加图标以便...

回答 1 投票 0

如何将按钮添加到首选项屏幕?

我对 Android 开发相当陌生,刚刚遇到了首选项。 我找到了 PreferenceScreen 并想用它创建一个登录功能。我唯一的问题是我不知道我如何

回答 10 投票 0

具有多个字段的多进程 PreferencesDataStore

Google 为 DataStore 的多进程版本提供的示例仅包含设置中的一个字段: 数据类设置( val 最后更新:长 ) 那么更新代码是: 范围.启动{

回答 1 投票 0

当我尝试使用首选项(数据存储)保存令牌时,应用程序闪烁

我这里有一个问题,问题是应用程序闪烁,当我尝试从 API 保存登录令牌时发生这种情况,我正在使用数据存储首选项来获取和设置令牌。在我添加

回答 1 投票 0

从 PreferenceScreen 导航到另一个 Fragment

使用 Android Jetpack 的导航组件,我有一个 MainActivity,其中包含 4 个不同的片段。这些片段之一是 SettingsFragment,它包含我来自 xml 文件的首选项....

回答 2 投票 0

PreferenceFragment - getPreferenceManager() 和 getPreferenceScreen() 之间的区别?

我已经实现了自己的 PreferenceFragment 子类(详细信息请参见此处),并且想要监听其中的首选项更改。 PreferenceFragment 为您提供了两种执行此操作的方法:

回答 3 投票 0

将工具栏添加到首选项屏幕片段

我正在尝试通过工具栏使用 Android Jetpack 设置指南。指南说根标签是 ,所以我不能在 xml 中包含工具栏。我正在使用 NoAct...

回答 3 投票 0

自定义 androidx 首选项渲染问题 - java.lang.ClassNotFoundException

当我尝试在 Android Studio - Design 中预览我的 settings.xml 时,它显示错误: 找不到 com.mypackage.preferences.SwitchPreferenceCompatFix。 但它存在于那里。 更详细的错误: 爪哇...

回答 0 投票 0

如何拦截android中的偏好修改

我有一个EditTextPreference,我希望用户在点击它时检查是否满足当前的修改条件。如果没有,会弹出对话框,否则修改...

回答 0 投票 0

如何在 Android 中更改偏好类别的文本颜色?

textColor 属性不起作用。这是我的 XML: 有什么想法吗?

回答 13 投票 0

嵌套的PreferenceFragmentCompat在Android 4.4上不显示。

我最近重构了我的Android应用程序,以使用PreferenceFragmentCompat,而不是被废弃的PreferenceActivity + PreferenceFragment。该应用程序使用了多个偏好屏幕的层次结构。I ...

回答 1 投票 0

刷新android PreferenceFragment

我在一个FragmentPreference里有一个CheckBoxPreference。当用户激活该复选框时,我检查是否安装了应用程序,如果没有,我就将该偏好值重置为false,然后我打开Play Store以 ...

回答 2 投票 12

实现AndroidX SeekBarPreference时的问题

我试图在我的Android设置PreferenceScreen中添加一个SeekBarPreference。例如,当我使用EditTextPreference时,一切都能正常工作,所以肯定是SeekBar导致了问题。...

回答 1 投票 0

当初始化时,DropDownPreference setOnPreferenceChangeListener会自己调用。

我已经在这里提交了一个关于这个问题的bug 我相信这是一个平台的bug。如果你有一个DropDownPreference OnPreferenceChangeListener,Android会出现 "选择 "第一个项目一次,而且只有一次,当......

回答 1 投票 0

能否在android系统的偏好设置中添加动画,就像在导航组件中一样。

有没有可能像导航组件中的动画一样,在偏好中添加一个动画来片段变化?安卓指南,所以我想执行像这里的东西。 ...

回答 1 投票 6

© www.soinside.com 2019 - 2024. All rights reserved.