从屏幕上删除/隐藏一个偏好设置

148

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

16个回答

219
如果您的偏好设置在一个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);

6
公平地说,上面的回答确实指出了你需要父级PreferenceCategory - matt

179

如果你有对于Preference和其父级(一个PreferenceCategoryPreferenceScreen)的引用,那么是可以的。

myPreferenceScreen.removePreference(myPreference);

我可能通过这个回答了自己的问题?https://dev59.com/IW445IYBdhLWcg3wydBk#4704360 - marienke
4
很遗憾,它会永久性地删除该偏好设置。是否可能只是隐藏它? - Dmitry
它对我也不起作用。偏好设置仍然存在! - Dmitry
@Dmitry,你可以使用 setEnabled() 来将其置为灰色。 - JakeD
1
@Dmitry 你需要在直接父级上调用 removePreference,可以使用 getParent() 获取它(参见此答案)。 - user905686

54

如果Preference是PreferenceScreen的直接子项,这里是一些独立的代码:

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

4
如果偏好设置位于类别内部,则此方法将无效。您需要使用findPreference方法搜索该类别,并从中删除偏好设置。 - MBH
1
@MBH:感谢您提到这个警告! - 1''

21
如果您正在使用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中有文档记录。

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

2
这是正确的答案!OP要求隐藏一个偏好,而不是删除。 - Francis Saa-Dittoh

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中不起作用。但将其更改为首选项(即使它是一组首选项)却可以工作。 - Rob
Rob,我刚在API22 AVD中测试了上面的代码,它完全正常工作。确保你的偏好XML内容与你的代码匹配。对于上面的示例,SwitchPreference可以放在任何地方,但你需要将PreferenceCategorys直接放在PreferenceScreen的子级中。 - James
我刚刚将类别作为首选项,没有强制转换,并将其删除。成功了。 - Rob

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

7

已接受的答案对于V7无效。使用setVisible在V7中有效。 - m12lrpv
V7还有getParent(),因此您可以按照此答案中所述删除首选项。 - user905686

3
在XML文件中,如果将标题和摘要标签保留为空,则可以创建一个隐藏的参数设置。
<EditTextPreference
    android:defaultValue="toddlerCam"
    android:key="save_photo_dir"
/>

这对我来说是完美的答案。我一直在寻找它。谢谢! - 夏期劇場

3

这也适用于API 26以下的AndroidX支持库。 - user905686

2
有一个简单的解决方法:
//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"/>

无论您喜欢将偏好设置隐藏在偏好设置组中还是根目录中,它都可以正常工作!


谢谢。对我来说完美无缺。但为了确保,我添加了:android:visibility="gone" - Mic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接