checkboxpreference android 或 listpreference 的依赖项中的多重依赖项

发布于 2024-10-28 11:17:52 字数 778 浏览 4 评论 0原文

例如:我的首选项屏幕中有三个复选框,每个复选框有 3 个不同的 listpreference(A,B,C) 。我想让用户一次只选择一个复选框。我该如何实现这一目标?

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

  2. 如果可以使用的话,我无法使用 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 的数组是“蓝色”,“红色”,“白色”

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

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

如果是白色的 ListPreference C 取决于白色

我该怎么做?

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

最好的问候,

提前感谢..

For example: i have three checkboxes in my preference screen and there is 3 different listpreference(A,B,C) depended on each checkbox. i want to make the user select only one checkbox at a time. How do i achieve this?

  1. There is no radio button in preference screen

  2. I can not use Listpreference , if i can use it

      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"
    

Array of this Listprefrence is "blue"," red", "white"

if it is blue
ListPreference A depends on blue

if it is red
ListPreference B depends on red

if it is white
ListPreference C depends on white

How can i do this?

i searched 3-4 pages in google and here almost everything about these but i could not find any answer.

Best Regards,

Thanks in advance..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

东风软 2024-11-04 11:17:52

您可以在 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
            }
        }
    }

You can override onSharedPreferenceChanged in your PreferenceActivity class and enable/disable appropriated Preferences programmatically:

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
            }
        }
    }
方觉久 2024-11-04 11:17:52

另一种方法是创建一个抽象帮助器类。它使用反射来访问 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>

Post Scriptum:
如果您不想使 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;
}

Another way is to create an abstract helper class. It uses reflection to access the method registerDependent() which sadly is private to the Preference class:

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

}

Then extend your checkboxPreference or any other class as follows:

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

Finally, you can use your new preference like this:

<?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>

Post Scriptum:
If you don't want to make the MultiDependecies class abstact and override the findPreferenceInHierarchy function, you can use reflection:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文