从屏幕上删除/隐藏首选项


134

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

Answers:


171

是的,如果您同时引用Preference及其父级(a PreferenceCategoryPreferenceScreen

myPreferenceScreen.removePreference(myPreference);

大!谢谢!运作并具有完美的意义
波士顿,2012年

我可能已经通过这个回答了我自己的问题?stackoverflow.com/a/4704360/956975
marienke '17

2
不幸的是,它永久删除了首选项。是否可以隐藏它?
德米特里(Dmitry)

这对我也不起作用。偏好仍然存在!
德米特里(Dmitry)'18

@Dmitry您可以使用setEnabled()
JakeD

212

如果您Preference位于内PreferenceCategory,则必须执行以下操作:

XML:

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

    <CheckBoxPreference
        android:key="checkPref" />

Java:

CheckBoxPreference mCheckBoxPref = (CheckBoxPreference) findPreference("checkPref");
PreferenceCategory mCategory = (PreferenceCategory) findPreference("category_foo");
mCategory.removePreference(mCheckBoxPref);

5
公平地说,以上答案确实表明您需要父母PreferenceCategory
马特

49

如果“首选项”是“首选项”屏幕的直接子代,则下面是一些独立代码:

PreferenceScreen screen = getPreferenceScreen();
Preference pref = getPreferenceManager().findPreference("mypreference");
screen.removePreference(pref);

4
如果首选项位于类别内,则此方法无效。您必须findPreference输入类别,然后从类别中删除首选项
MBH

1
@MBH:感谢您提出警告!
1英寸

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();
    }
}

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


这种情况行不通,至少在22种情况下行不通。但是将其更改为“首选项”(即使它是一组首选项)确实可以工作。
罗布2015年

Rob,我刚刚在API22 AVD中测试了上面的代码,并且工作正常。确保您的首选项XML内容与您的代码匹配。对于上面的示例,SwitchPreference可以在任何位置,但是您需要PreferenceCategorys成为PreferenceScreen的直接子代。
詹姆斯

我只是将类别作为首选项,没有强制转换,并将其删除。工作了
罗布2015年

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

8

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

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

preferences.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

PreferenceFragmentCompathttps://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();
    }
} 


3

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

<EditTextPreference
    android:defaultValue="toddlerCam"
    android:key="save_photo_dir"
/>

这是对我的完美答案。我一直在寻找。谢谢!
夏期剧场

2

这是执行此操作的通用方法,无论首选项是否位于a PreferenceCategory或之下PreferenceScreen

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;
}


0

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

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函数来设置可见性。

按照文档茶的回答 setVisible()是,因为支持库的24.1.0版本。
JJD

你看过我写的吗?我特地写,它可能现在......此外,第一解决方案有助于去除,这比隐藏有点不同..
Android开发者

是的,我读了你的答案。我指的是你的第二点。它看起来好像该setVisibile()方法可从我试图阐明的android-x中获得。请不要冒犯。
JJD

Android-X是取代所有支持库的一种。我们不会提供任何新版本的支持库。
android开发人员

正确。我知道这一点。仍然,那些坚持以前版本的人可以使用该方法。
JJD

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);

1
抱歉,这是英文网站。你能用英语回答吗?
Dave Schweisguth's

当然,我的目的还在于为不会说英语的人提供帮助
Gustavo Eduardo Belduma 2016年

3
@GustavoEduardoBelduma,那么您可能需要阅读此meta.stackoverflow.com/a/297680/545026
Leo支持Monica Cellio '16

0

如果您正在执行我认为正在尝试执行的操作(因为我现在正在尝试执行此操作),则启用/禁用首选项可能会更好。因为删除它会将其从首选项屏幕中删除,并且如果通过编程方式制作了该屏幕,则可能无法将其添加回所需的位置。

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

尽管可能不建议这样做。它适用于我现在正在研究的用例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.