【问题标题】:multiple dependency in checkboxpreference android or listpreference's dependencycheckboxpreference android或listpreference的依赖中的多重依赖
【发布时间】:2011-03-30 09:21:46
【问题描述】:

例如:我的首选项屏幕中有三个复选框,并且有 3 个不同的 listpreference(A,B,C) 取决于每个复选框。我想让用户一次只选择一个复选框。我如何做到这一点?

  1. 首选项屏幕中没有单选按钮

  2. 我不能使用 Listpreference ,如果我可以使用它

      ListPreference
        android:key="livewallpaper_testpattern"
        android:title="@string/livewallpaper_settings_title"
        android:summary="@string/livewallpaper_settings_summary"
        android:entries="@array/livewallpaper_testpattern_names"
        android:entryValues="@array/livewallpaper_testpattern_prefix"
    

这个 Listprefrence 的数组是 "blue","re​​d","white"

如果它是蓝色的 ListPreference A 取决于蓝色

如果它是红色的 ListPreference B 取决于红色

如果它是白色的 ListPreference C 依赖于白色

我该怎么做?

我在谷歌搜索了 3-4 页,这里几乎所有关于这些的内容,但我找不到任何答案。

最好的问候,

提前谢谢..

【问题讨论】:

    标签: android preferences listpreference checkboxpreference


    【解决方案1】:

    您可以在 PreferenceActivity 类中覆盖 onSharedPreferenceChanged 并以编程方式启用/禁用适当的首选项:

    public class MyPreferences extends PreferenceActivity implements OnSharedPreferenceChangeListener {
        ...
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            if (key.equals("livewallpaper_testpattern")) {
                if (/* check if livewallpaper_testpattern equals to blue */) {
                    findPreference("ListPreferenceKey_A").setEnabled(true);
                    findPreference("ListPreferenceKey_B").setEnabled(false);
                    findPreference("ListPreferenceKey_C").setEnabled(false);
                } else if (/* check if livewallpaper_testpattern equals to red */) {
                    // enable B, disable A & C
                } else if (/* check id livewallpaper_testpattern equals to white */) {
                    // enable C, disable A & B
                }
            }
        }
    

    【讨论】:

      【解决方案2】:

      另一种方法是创建一个抽象辅助类。它使用反射来访问 registerDependent() 方法,遗憾的是它是 Preference 类的私有方法:

      public abstract class MultiDependencies {
      
          private static final String NOLESHNS="http://nolesh.com";
      
          private Preference host;        
          private HashMap<String, Boolean> dependencies = new HashMap<>();
      
          //We have to get access to the 'findPreferenceInHierarchy' function
          //from the extended preference, because this function is protected
          protected abstract Preference findPreferenceInHierarchy(String key);
      
          public MultiDependencies(Preference host, AttributeSet attrs){
      
              this.host = host;
      
              final String dependencyString = getAttributeStringValue(attrs, NOLESHNS, "dependencies", null);
      
              if (dependencyString != null) {
                  String[] dependencies = dependencyString.split(",");
                  for (String dependency: dependencies) {
                      this.dependencies.put(dependency.trim(), false);
                  }
              }
          }
      
          void onAttachedToActivity(){
              if(isEnabled()) registerDependencies();
          }
      
          void onDependencyChanged(Preference dependency, boolean disableDependent){
              setDependencyState(dependency.getKey(), !disableDependent);
              setHostState();
          }
      
          private void setDependencyState(String key, boolean enabled){
              for (Map.Entry<String, Boolean> entry: dependencies.entrySet()) {
                  if (entry.getKey().equals(key)) entry.setValue(enabled);
              }
          }
      
          private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) {
              String value = attrs.getAttributeValue(namespace, name);
              if(value == null) value = defaultValue;
              return value;
          }
      
          private void registerDependencies() {
              for (final Map.Entry<String, Boolean> entry: dependencies.entrySet()) {
                  final Preference preference = findPreferenceInHierarchy(entry.getKey());
      
                  if (preference != null) {
      
                      try {
                          final Class<Preference> prefClass = Preference.class;
                          final Method registerMethod = prefClass.getDeclaredMethod("registerDependent", Preference.class);
                          registerMethod.setAccessible(true);
                          registerMethod.invoke(preference, host);
                      } catch (final Exception e) {
                          e.printStackTrace();
                      }
      
                      boolean enabled = preference.isEnabled();
                      if(preference instanceof CheckBoxPreference){
                           enabled &= ((CheckBoxPreference) preference).isChecked();
                      }
      
                      setDependencyState(preference.getKey(), enabled);
                  }
              }
              setHostState();
          }
      
          private void setHostState(){
              boolean enabled = true;
              for (Map.Entry<String, Boolean> entry: dependencies.entrySet()) {
                  if (!entry.getValue()){
                      enabled = false;
                      break;
                  }
              }
              host.setEnabled(enabled);
          }
      
          public boolean isEnabled(){
              return dependencies.size()>0;
          }
      
      }
      

      然后扩展您的checkboxPreference 或任何其他类,如下所示:

      public class MultiDependencyCheckboxPrereference extends CheckBoxPreference {
      
          MultiDependencies multiDependencies;
      
          public MultiDependencyCheckboxPrereference(Context context, AttributeSet attrs) {
              super(context, attrs);
      
              multiDependencies = new MultiDependencies(this, attrs) {
                  @Override
                  protected Preference findPreferenceInHierarchy(String key) {
                      //Getting access to the protected function
                      return MultiDependencyCheckboxPrereference.this.findPreferenceInHierarchy(key);
                  }
              };
          }
      
          @Override
          protected void onAttachedToActivity() {
              super.onAttachedToActivity();
              multiDependencies.onAttachedToActivity();
          }
      
          @Override
          public void onDependencyChanged(Preference dependency, boolean disableDependent) {
              if(multiDependencies.isEnabled()) 
                  multiDependencies.onDependencyChanged(dependency, disableDependent);
              else super.onDependencyChanged(dependency, disableDependent);
          }
      }
      

      最后,您可以像这样使用您的新偏好:

      <?xml version="1.0" encoding="utf-8"?>
      <PreferenceScreen 
          xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:nolesh="http://nolesh.com">
      
      <com.nolesh.android.widgets.MultiDependencyCheckboxPrereference
          android:key="com_nolesh_test"
          android:defaultValue="false"
          android:title="test"
          nolesh:dependencies="com_nolesh_dep1, com_nolesh_dep2"
          />
      
      <CheckBoxPreference
          android:key="com_nolesh_dep1"
          android:defaultValue="false"
          android:title="dependency 1"
          />
      
      <CheckBoxPreference
          android:key="com_nolesh_dep2"
          android:defaultValue="false"
          android:title="dependency 2"
          />
      
      </PreferenceScreen>
      

      后记: 如果您不想让MultiDependecies 类抽象并覆盖findPreferenceInHierarchy 函数,您可以使用反射:

      private Preference findPreferenceInHierarchy(String key){
          try {
              final Class<Preference> prefClass = Preference.class;
              final Method registerMethod = prefClass.getDeclaredMethod(
                          "findPreferenceInHierarchy", String.class);
              registerMethod.setAccessible(true);
              return (Preference) registerMethod.invoke(host, key);
          } catch (final Exception e) {
              e.printStackTrace();
          }
          return null;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-27
        • 2012-03-10
        • 2019-03-06
        • 2014-07-26
        • 2015-05-09
        • 1970-01-01
        • 2013-06-16
        • 2020-02-14
        相关资源
        最近更新 更多