【问题标题】:Remove/hide a preference from the screen从屏幕上删除/隐藏首选项
【发布时间】:2011-01-15 11:14:30
【问题描述】:

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

【问题讨论】:

    标签: android preferences


    【解决方案1】:

    如果您的PreferencePreferenceCategory 内,您必须这样做:

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

    【讨论】:

    • 公平地说,上面的答案确实说你需要父母PreferenceCategory
    【解决方案2】:

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

    myPreferenceScreen.removePreference(myPreference);
    

    【讨论】:

    • 太棒了!谢谢!有效且非常有意义
    • 我可能已经通过这个回答了我自己的问题? stackoverflow.com/a/4704360/956975
    • 不幸的是,它会永久删除首选项。是否有可能只是隐藏它?
    • 它也对我不起作用。偏好仍然存在!
    • @Dmitry 您需要在直接父级上调用removePreference,您可以通过getParent() 获得(参见this answer)。
    【解决方案3】:

    如果首选项是首选项屏幕的直接子项,这里有一些独立代码:

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

    【讨论】:

    • 如果首选项位于类别内,这将不起作用。您必须为该类别findPreference,并从该类别中删除首选项
    • @MBH:感谢您提及该警告!
    【解决方案4】:

    如果您使用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();
        }
    } 
    

    【讨论】:

    • 这是正确答案!! OP 要求隐藏首选项,而不是删除。
    【解决方案5】:

    如果您想要动态更改首选项的东西,例如在 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,我刚刚在 API22 AVD 中测试了上面的代码,它工作得很好。确保您的偏好 XML 内容与您的代码匹配。对于上面的示例,SwitchPreference 可以在任何地方,但您需要 PreferenceCategorys 是 PreferenceScreen 的直接子级。
    • 我只是将类别作为首选项,没有演员表,然后将其删除。工作。
    【解决方案6】:

    在您的 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() 方法。但我还没有尝试过。因此,您必须使用PreferenceFragment 而不是PreferenceActivity

      【讨论】:

      • 接受的答案不适用于 V7。使用 setVisible 确实适用于 V7
      • V7 也有getParent(),因此您实际上可以按照this answer 中的说明删除首选项。
      【解决方案8】:

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

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

      【讨论】:

      • 这对我来说是完美的答案。我一直在寻找这个。谢谢!
      【解决方案9】:

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

      虽然您可以执行以下操作:

      preference.getParent().removePreference(preference);
      

      【讨论】:

      • 这也适用于 API 26 以下的 androidx 支持库。
      【解决方案10】:

      这是一种通用的方法,无论偏好是在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;
      }
      

      【讨论】:

        【解决方案11】:

        您可以通过两种方式做到这一点:

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

        【讨论】:

        • 根据docsTea's answer setVisible() 从支持库的版本 24.1.0 开始可用。
        • 你看过我写的吗?我特地写了现在有可能......另外,第一个解决方案有助于删除,这与隐藏有点不同......
        • 是的,我阅读了您的回答。我指的是你的第二点。它读起来好像setVisibile() 方法可以从我试图澄清的 android-x 获得。请不要冒犯。
        • Android-X 是替代所有支持库的版本。正如我们所知,不会有任何新版本的支持库。
        • 正确。我是aware of this。尽管如此,被旧版本卡住的人仍然可以使用该方法。
        【解决方案12】:

        如果您想评估,并基于该掩码,替代方案可能是

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

        【讨论】:

        • 对不起,这是一个英文网站。你能用英文回答吗?
        • 当然我的意图也是为不会说英语的人提供服务
        • @GustavoEduardoBelduma 那么你可能需要阅读这个meta.stackoverflow.com/a/297680/545026
        【解决方案13】:

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

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

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

        【讨论】:

          【解决方案14】:

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

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

          代码在 kotlin 中

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

          【讨论】:

            【解决方案15】:

            有一个简单的解决方法:

            //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 中或在根目录中),它都会起作用!

            【讨论】:

              猜你喜欢
              • 2014-06-09
              • 1970-01-01
              • 1970-01-01
              • 2020-10-03
              • 2014-03-16
              • 2015-07-13
              • 2023-04-02
              • 1970-01-01
              • 2011-07-31
              相关资源
              最近更新 更多