当前位置: 首页 > 知识库问答 >
问题:

在Android MultiSelectListPreference中至少选择一个项目

隗俊誉
2023-03-14

我现在已经通过互联网搜索了几个小时,到目前为止还没有找到任何实质性的东西。我想做的事情是一个多选择偏好视图,禁用最后一个项目和重新启用它,如果它不再是单独的。

我通过到目前为止关于采取超类强制读取私有变量在那里编写我自己的onPrepareDialogBuilder(alertDialog.BuilderBuilder)。它正在配置自己的onMultiChoiceClickListener,该跳入其中,此时只剩下一个项目。这里的问题是,我使用了一个不好的练习强制读取私有变量,而且我到目前为止还不知道如何获得复选框项和如何禁用它。但我认为深入研究Android SDK会解决这个问题。

最后,如果什么都不起作用,那么如果用户选择的项目少于一个,则通过覆盖onPreferenceChangelistener来显示祝词来解决问题。但是用户友好性是一个很高的价值,这是需要获得的,而这往往并不容易。

THX.

import android.content.Context;
import android.preference.MultiSelectListPreference;
import android.util.AttributeSet;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import georg.com.flironetest_01.Variables.Units;

/**
 * Created by Georg on 16/03/16.
 */
public class UnitMultipleSelectorPreference extends MultiSelectListPreference {

    public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
        super(context, attrs);

        List<CharSequence> humanU = new ArrayList<>();
        List<CharSequence> machineU = new ArrayList<>();

        Units[] all = Units.values(); // Units is a enum with a rewriten to string statement.
        for (Units elem : all) {
            humanU.add(elem.toString());
            machineU.add(elem.name());
        }

        setEntries(humanU.toArray(new CharSequence[humanU.size()]));
        setEntryValues(machineU.toArray(new CharSequence[machineU.size()]));

        Set<String> mU = new HashSet<>();
        mU.add(Units.C.name());
        mU.add(Units.K.name());

        setDefaultValue(mU);
    }
}

共有1个答案

罗鸿畴
2023-03-14

好吧。在“自我就是男人”这句格言之后,我在这里回答我自己的问题:我最终编程了我自己的偏好面板。下面是代码。如果有人想看看它,并给一些时间如何使它更稳定:请随意。

但是总结一下我所做的:我创建了自己的ArrayAdapter。但是DialogPreference不允许我创建自己的多选择器。您需要更改最终的对话框片段以创建一个工作的多选择器列表(请参见此处:https://stackoverflow.com/a/17907379/5759814)。如果您使用DialogPreferences,那么这不是一个容易的任务。原因是这些少量的代码

/**
 * Shows the dialog associated with this Preference. This is normally initiated
 * automatically on clicking on the preference. Call this method if you need to
 * show the dialog on some other event.
 * 
 * @param state Optional instance state to restore on the dialog
 */
protected void showDialog(Bundle state) {
    Context context = getContext();

    mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;

    mBuilder = new AlertDialog.Builder(context)
        .setTitle(mDialogTitle)
        .setIcon(mDialogIcon)
        .setPositiveButton(mPositiveButtonText, this)
        .setNegativeButton(mNegativeButtonText, this);

    View contentView = onCreateDialogView();
    if (contentView != null) {
        onBindDialogView(contentView);
        mBuilder.setView(contentView);
    } else {
        mBuilder.setMessage(mDialogMessage);
    }

    onPrepareDialogBuilder(mBuilder);

    getPreferenceManager().registerOnActivityDestroyListener(this);

    // Create the dialog
    final Dialog dialog = mDialog = mBuilder.create();
    if (state != null) {
        dialog.onRestoreInstanceState(state);
    }
    if (needInputMethod()) {
        requestInputMethod(dialog);
    }
    dialog.setOnDismissListener(this);
    dialog.show();
}

正如您所看到的,这里有一个通过onpreparedialogbuilder触发的方法来更改我的对话框生成器,但似乎没有任何其他函数在之后触发,允许我在创建对话框之后直接更改它。第二个想法是更改onPrepareDialogBuilder,以便在那里初始化所有内容,但实际上没有什么帮助,因为我最终会显示对话框窗口。这让我决定创建一个完全属于自己的偏好类。有了这个决定,我就松开了所有准备好的函数,比如onrestoreInstanceState和Co,但是我现在有了一个具有更持久流的应用程序,当我为热视图选择零单元时,它不会做任何愚蠢的事情。

在非注释代码下面。我很抱歉,但我想这对每个在这里降落的人来说已经足够简单了。

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import georg.com.flironetest_01.Variables.Units;

/**
 * Created by Georg on 16/03/16.
 */
public class UnitMultipleSelectorPreference extends Preference implements DialogInterface.OnClickListener, Preference.OnPreferenceClickListener {

    String[] human_entries = null;
    String[] machine_entries = null;



    public SharedPreferences prev;

    public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
        super(context, attrs);


        prev = getSharedPreferences();

        List<String> humanU = new ArrayList<>();
        List<String> machineU = new ArrayList<>();

        Units[] all = Units.values();
        for (Units elem : all) {
            humanU.add(elem.toString());
            machineU.add(elem.name());
        }

        human_entries = humanU.toArray(new String[humanU.size()]);
        machine_entries = machineU.toArray(new String[machineU.size()]);

        Set<String> mU = new HashSet<>();
        mU.add(Units.C.name());
        mU.add(Units.K.name());

        setDefaultValue(mU);

        setOnPreferenceClickListener(this);
    }

    boolean[] selected = new boolean[0];

    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
        if (prev == null)
            return;

        if (human_entries == null || machine_entries == null || human_entries.length != machine_entries.length ) {
            throw new IllegalStateException(
                    "ListPreference requires an entries array and an entryValues array which are both the same length");
        }

        selected = new boolean[human_entries.length];
        for (int i = 0; i < human_entries.length; i++)
            selected[i] = prefSet.contains(machine_entries[i]);


        String[] stringObj = new String[human_entries.length];
        int i = 0;
        for(CharSequence ch : human_entries)
            stringObj[i++] = ch.toString();


        builder.setAdapter(new MyAdapter(getContext(), android.R.layout.simple_list_item_multiple_choice, stringObj), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        });

        AlertDialog mDialog = builder.create();
        mDialog.getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
        mDialog.getListView().setItemsCanFocus(false);
        mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                // Manage selected items here

                ListView mParent = (ListView)parent;


                if (mParent.getCheckedItemCount() >= 1)
                    selected[position] = mParent.isItemChecked(position);
                if (mParent.getCheckedItemCount() == 0)
                    mParent.setItemChecked(position, true);
            }
        });


        mDialog.show();



        i = 0;
        for (boolean select : selected)
            mDialog.getListView().setItemChecked(i++, select);
    }

    @Override
    public boolean onPreferenceClick(Preference preference) {
        AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext());
        mBuilder.setTitle(getTitle())
                .setPositiveButton(android.R.string.ok, this)
                .setNegativeButton(android.R.string.cancel, this);
        onPrepareDialogBuilder(mBuilder);

        return true;
    }



    @Override
    public void onClick(DialogInterface dialog, int which) {
        Toast.makeText(getContext(), "W:"+which + " | " + Arrays.toString(selected), Toast.LENGTH_SHORT).show();

        switch (which) {
            case -1:
                if (isPersistent()) {
                    prefSet = new HashSet<>();

                    for (int i = 0; i < selected.length; i++) {
                        if (selected[i])
                            prefSet.add(machine_entries[i]);
                    }
                    getEditor().putStringSet(getKey(), prefSet).apply();

                    Toast.makeText(getContext(), "W:"+which + " | " + getSharedPreferences().getStringSet(getKey(),null).toString(), Toast.LENGTH_SHORT).show();

                }
                return;
        }
    }



    public class MyAdapter extends ArrayAdapter<String> {

        public MyAdapter(Context context, int textViewResourceId, String[] objects) {
            super(context, textViewResourceId, objects);
        }

        @Override
        public boolean isEnabled(int n) {
            return true;
        }
    }

    Set<String> prefSet;

    @Override
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
        super.onSetInitialValue(restorePersistedValue, defaultValue);
        prev = getSharedPreferences();

        if(restorePersistedValue) {
            prefSet = prev.getStringSet(getKey(), new HashSet<String>());
        } else {
            try {
                prefSet = (Set<String>)defaultValue;
                if(isPersistent())
                    getEditor().putStringSet(getKey(), prefSet);
            } catch (ClassCastException e) {
                Log.e("ERROR_CAST", "Error casting the default value to Set<String>.");
            }
        }
    }
}
 类似资料:
  • 我想允许至少3个复选框将检查,我试过下面的代码但它不是很好地工作。 HTML... jQuery 有人请帮助我,我如何选择至少2个复选框?

  • 我有一个带有一组相关复选框的ASP.NET webform。我想验证当单击提交按钮时,组中至少选中了一个复选框。我尝试过实现两种不同的解决方案,但都没有成功。当我尝试按类名返回选中复选框的长度时,收到0。当我尝试按名称返回ischecked值时,收到false。如果我查看页面的源,复选框具有“checked”属性。有人能检查我的html,让我知道我做错了什么吗?

  • 我会尽量说得具体些。我有一个navbar可以有动态添加的选项卡,当点击附加选项卡时,这些附加选项卡也可以通过点击关闭按钮移除。以下是HTML: li标签是动态添加和删除的,li标签中的活动类显示不同的图像,使得标签可以区分,从而活动类在li标签之间切换。 要关闭选项卡,脚本是: 我只想要至少一个活动选项卡,即使活动选项卡被用户移除。当前,当我关闭活动选项卡时,没有活动类,使选项卡相似。

  • 我最近将我的Android Studio更新到2.3.3版。尝试生成签名APK时,我收到错误消息: 请至少选择一个要使用的签名版本 有两个选项:V1 (Jar签名)和V2(完全APK签名)。我不确定选择哪一个。以及选择一个而不是另一个或者两个都选有什么好处? 提前感谢您的建议。

  • 我有两个表和 names表有以下列表: -男性姓名从nameID 1到nameID 10 -女性姓名从nameID 11到nameID 21 -两者都从nameID 23到nameID 31 性别表有三个属性: -女性 -男性 -两者 我正在使用引导选择选项,我想显示从nameID11到nameid21的名称,如果用户从gender选择选项中选择女性,等等,这是可能的吗?我看到其他帖子,我注意到他

  • 我试图让用户从JSF中的下拉列表中选择一个集合项。这是我正在使用的代码: 这是MyBean的代码: 如果需要,我的getter和setter为用户: 我的问题是,当它打印“所选用户是”时,没有写入用户。toString(),但用户列表。toString()!就像SelectOne菜单一样,它的设置不正确,但我已经搜索了很多。有人能帮忙吗?谢谢,安