我有一个 Android Widget,它使用 Web 服务来检索并在 Widget 上显示数据。该小部件具有扩展 PreferenceActivity 的配置活动。配置活动...
如何删除 Jetpack DataStore 创建的首选项文件
我有一个多用户应用程序,并使用 DataStore 为每个用户创建一个首选项文件。我希望能够在用户取消注册后删除 DataStore 创建的文件。我找到了这个
如何在 PreferenceFragment 中使 Preference 可长点击?
这里有一个类似的问题,但假设使用 PreferenceActivity。 但是,如何在没有 PreferenceActivity 的情况下(例如使用 PreferenceFragm 时)使首选项可长点击...
如何在Android中以编程方式获取SharedPreferences的所有键?
如何获取 SharedPreferences 中的所有键,而不是仅获取首选项的值? prefA = getSharedPreferences("MyAttack", MODE_PRIVATE); prefB= getSharedPreferences("MySkill", MODE_PRIVATE);
调整 androidx.preference 对话框以遵循 Material You
我有两个包含首选项部分的应用程序,我正在使用首选项库,这是撰写本文时可用的最新版本: 实现“androidx.preference:preference:1...
为什么使用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(); } }
我从 SharedPreferences 切换到 Jetpack DataStore。 我无法在仪器测试中模拟来自数据存储调用的数据 声明中 val dataStore = context.createDataStore(名称...
我在首选项屏幕内创建了一个首选项条目,如下所示: 我在首选项屏幕内创建了一个首选项条目,如下所示: <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 } }
Android:SharedPreference:启动时未设置默认值
我的应用程序中有列表首选项。它们似乎没有在安装后立即设置为默认值 - 它们似乎为空。我试图找出为什么我的默认首选项不是...
如何替换 setTargetFragment() 既然它已被弃用
setTargetFragment() 在 Java 中已被弃用,我不明白它的正确替代品,因为 android 文档使用它并且已经过时了。我相信 FragmentManager 是正确的替代品...
如何将图标添加到 android:drawable 文件夹中?
我将图标放在preferences.xml 文件中的选项旁边。我正在寻找一些图标来代表我拥有的特定选项,但找不到它们。所以我想知道如何添加图标以便...
我对 Android 开发相当陌生,刚刚遇到了首选项。 我找到了 PreferenceScreen 并想用它创建一个登录功能。我唯一的问题是我不知道我如何
具有多个字段的多进程 PreferencesDataStore
Google 为 DataStore 的多进程版本提供的示例仅包含设置中的一个字段: 数据类设置( val 最后更新:长 ) 那么更新代码是: 范围.启动{
我这里有一个问题,问题是应用程序闪烁,当我尝试从 API 保存登录令牌时发生这种情况,我正在使用数据存储首选项来获取和设置令牌。在我添加
从 PreferenceScreen 导航到另一个 Fragment
使用 Android Jetpack 的导航组件,我有一个 MainActivity,其中包含 4 个不同的片段。这些片段之一是 SettingsFragment,它包含我来自 xml 文件的首选项....
PreferenceFragment - getPreferenceManager() 和 getPreferenceScreen() 之间的区别?
我已经实现了自己的 PreferenceFragment 子类(详细信息请参见此处),并且想要监听其中的首选项更改。 PreferenceFragment 为您提供了两种执行此操作的方法:
我正在尝试通过工具栏使用 Android Jetpack 设置指南。指南说根标签是 ,所以我不能在 xml 中包含工具栏。我正在使用 NoAct...
自定义 androidx 首选项渲染问题 - java.lang.ClassNotFoundException
当我尝试在 Android Studio - Design 中预览我的 settings.xml 时,它显示错误: 找不到 com.mypackage.preferences.SwitchPreferenceCompatFix。 但它存在于那里。 更详细的错误: 爪哇...
我有一个EditTextPreference,我希望用户在点击它时检查是否满足当前的修改条件。如果没有,会弹出对话框,否则修改...