146

我有一个扩展 PreferenceActivity 的活动。我正在从 xml 文件加载首选项。但在某些情况下,我需要根据我的应用程序状态从屏幕上完全隐藏其中一项首选项。有一个 setEnabled 方法,但这不是我想要的。我想完全从屏幕上删除该偏好。是否可以 ?

4

15 回答 15

219

如果你Preference在 a 内PreferenceCategory,你必须这样做:

XML:

<PreferenceCategory
    android:key="category_foo"
    android:title="foo">

    <CheckBoxPreference
        android:key="checkPref" />

爪哇:

CheckBoxPreference mCheckBoxPref = (CheckBoxPreference) findPreference("checkPref");
PreferenceCategory mCategory = (PreferenceCategory) findPreference("category_foo");
mCategory.removePreference(mCheckBoxPref);
于 2011-04-18T15:18:01.080 回答
177

是的,如果您同时引用了Preference和它的父级(aPreferenceCategoryPreferenceScreen

myPreferenceScreen.removePreference(myPreference);
于 2010-02-10T21:07:56.397 回答
54

在首选项是首选项屏幕的直接子项的情况下,这里有一些独立代码:

PreferenceScreen screen = getPreferenceScreen();
Preference pref = getPreferenceManager().findPreference("mypreference");
screen.removePreference(pref);
于 2013-09-17T16:43:37.637 回答
18

如果您使用的是PreferenceFragmentCompat,您可以在 xml 中设置可见性。

您的 xml 中的首选项将自动转换为 AppCompat 版本。然后,您可以在 xml 中使用“ app:isPreferenceVisible ”属性

首选项.xml

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

    <CheckBoxPreference
        android:defaultValue="false"
        android:key="show.navigation"
        android:title="Show navigation"
        app:isPreferenceVisible="false" />

...

该属性记录在https://developer.android.com/guide/topics/ui/settings/components-and-attributes

添加PreferenceFragmentCompat记录在https://developer.android.com/guide/topics/ui/settings/#inflate_the_hierarchy

例子:

public class MySettingsActivity extends AppCompatActivity {

    public static class MySettingsFragment extends PreferenceFragmentCompat {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.preferences, rootKey);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.settings_container, new MySettingsFragment())
                .commit();
    }
} 
于 2019-01-11T22:05:43.930 回答
9

如果您想要动态更改偏好设置的东西,例如在 SwitchPreference 上,我发现最好的方法是将所有子选项放入两个类别容器中。最初您将显示所有内容,然后您只需删除不需要的位。聪明的一点是,当某些事情发生变化时,您只需触发重新创建,然后您不必手动创建任何内容或担心以正确的顺序放回事物。

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  addPreferencesFromResource(R.xml.preferences);
  PreferenceCategory prefCatOne= (PreferenceCategory)findPreference("prefCatOne");
  PreferenceCategory prefCatTwo= (PreferenceCategory)findPreference("prefCatTwo");
  SwitchPreference mySwitchPref= (SwitchPreference)findPreference("mySwitchPref");
  PreferenceScreen screen = getPreferenceScreen();
  if (mySwitchPref.isChecked()) {
    screen.removePreference(prefCatOne);
  } else {
    screen.removePreference(prefCatTwo);
  }
}

public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    if (key.equals("mySwitchPref")) {
        this.recreate();
    }
}

我可以看到的唯一缺点是屏幕是从头开始重新创建的,因此会出现闪光。

于 2015-02-16T04:27:03.457 回答
8

在您的 XML 文件中:

<PreferenceScreen 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:key="preferenceScreen">

    <PreferenceCategory
        android:key="personalisation"
        android:title="your title here">

        <ThemedPreference
            android:key="animation" />

</PreferenceScreen>

在您的代码中:

PreferenceScreen pPreferenceScreen = (PreferenceScreen) findPreference("preferenceScreen");

PreferenceCategory pCategory = (PreferenceCategory) findPreference("personalisation");
ThemedPreference pThemePref = (ThemedPreference) findPreference("animation");

pPreferenceScreen.removePreference(pCategory); //remove category
pCategory.removePreference(pThemePref);   // remove preference
于 2017-07-24T06:36:04.310 回答
7

我推荐使用 v7 首选项,它有setVisible()方法。但我还没有尝试过。因此,您必须使用PreferenceFragment而不是PreferenceActivity.

于 2017-06-09T03:30:20.533 回答
3

在 XML 文件中,您可以通过将标题和摘要标签留空来进行隐藏首选项。

<EditTextPreference
    android:defaultValue="toddlerCam"
    android:key="save_photo_dir"
/>
于 2018-04-16T22:38:44.917 回答
3

由于 Android API 26getParent()方法可用:https://developer.android.com/reference/android/preference/Preference.html#getParent()

尽管您可以执行以下操作:

preference.getParent().removePreference(preference);
于 2018-09-14T17:11:52.220 回答
2

这是执行此操作的通用方法,无论首选项是否在 aPreferenceCategoryPreferenceScreen.

private void removePreference(Preference preference) {
    PreferenceGroup parent = getParent(getPreferenceScreen(), preference);
    if (parent == null)
        throw new RuntimeException("Couldn't find preference");

    parent.removePreference(preference);
}

private PreferenceGroup getParent(PreferenceGroup groupToSearchIn, Preference preference) {
    for (int i = 0; i < groupToSearchIn.getPreferenceCount(); ++i) {
        Preference child = groupToSearchIn.getPreference(i);

        if (child == preference)
            return groupToSearchIn;

        if (child instanceof PreferenceGroup) {
            PreferenceGroup childGroup = (PreferenceGroup)child;
            PreferenceGroup result = getParent(childGroup, preference);
            if (result != null)
                return result;
        }
    }

    return null;
}
于 2017-05-25T02:39:12.707 回答
0

如果您想评估并基于该掩码,则可能是另一种选择

SwitchPreference autenticacionUsuario = 
    (SwitchPreference) findPreference("key_autenticacion_usuario");

final EditTextPreference Username = 
    (EditTextPreference) findPreference("key_username_mqtt");
final EditTextPreference Password = 
    (EditTextPreference) findPreference("key_password_mqtt");

if (!autenticacionUsuario.isChecked()) {
    PreferenceCategory preferenceCategory = 
        (PreferenceCategory) findPreference("category_mqtt");
    preferenceCategory.removePreference(Username);
    preferenceCategory.removePreference(Password);
}

这一切都必须在

public static class PrefsFragment extends PreferenceFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
于 2016-05-12T23:38:16.753 回答
0

您可以通过 2 种方式执行此操作:

1.如果您使用支持库,您可以构建偏好树及其父项的映射,然后使用其父项删除偏好。这是生成此类地图的函数:

public static Map<Preference, PreferenceGroup> buildPreferenceParentTree(@NonNull final PreferenceScreen preferenceScreen) {
    final Map<Preference, PreferenceGroup> result = new HashMap<>();
    final Stack<PreferenceGroup> curParents = new Stack<>();
    curParents.add(preferenceScreen);
    while (!curParents.isEmpty()) {
        final PreferenceGroup parent = curParents.pop();
        final int childCount = parent.getPreferenceCount();
        for (int i = 0; i < childCount; ++i) {
            final Preference child = parent.getPreference(i);
            result.put(child, parent);
            if (child instanceof PreferenceGroup)
                curParents.push((PreferenceGroup) child);
        }
    }
    return result;
}
  1. 如果你使用新的 android-x 偏好 API,你可以通过使用setVisible函数来设置可见性。
于 2018-10-09T11:41:06.263 回答
0

如果您正在做我认为您正在尝试做的事情(因为我现在正在尝试这样做),那么启用/禁用首选项可能会更好。因为删除它会将其从首选项屏幕中移除,并且如果您以编程方式制作屏幕,您可能无法将其添加回您想要的位置。

pref.setEnabled(false); pref.setEnabled(true);

尽管这可能已被弃用。它适用于我现在正在经历的用例。

于 2019-12-12T16:17:07.290 回答
0

如果您只需要不显示偏好,即隐藏偏好,请执行以下操作

findPreference<Preference>("keyName").isVisible = false

代码在 kotlin

注意:这是 AndroidX 偏好设置(不知道是否与之前的偏好设置相同)

于 2021-05-14T07:58:44.223 回答
0

有一个简单的解决方法:

//In your Activity code after finding the preference to hide:
    if(pref!=null) {
        pref.setEnabled(false);
        pref.setSelectable(false);
        //Following line will replace the layout of your preference by an empty one
        pref.setLayoutResource(R.layout.preference_hidden);
    }

并创建一个 preference_hidden 布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp"/>

无论您喜欢隐藏在哪里(在 PreferenceGroup 中或在根目录中),它都会起作用!

于 2021-05-28T22:35:56.013 回答