如何使用Android Spinner作为下拉列表

Amo*_*ter 20 android selection spinner

我花了很长时间才知道Android Spinner.经过几次失败的实施尝试,并且在阅读了许多与我自己的问题部分相似但没有令人满意的答案的问题之后,还有一些没有任何答案,例如这里这里,我终于得到Android中的"微调器"并不意味着与桌面应用程序中的"下拉列表"或HTML中的选择相同.然而,我的应用程序(我猜测所有其他问题相似的海报的应用程序)需要的东西就像一个下拉框,而不是像一个微调器.

我的两个问题是我最初认为是OnItemSelectedListener的特殊性(我在这个网站上看到这些是单独的问题而不是一个):

  1. 在没有用户交互的情况下自动触发第一个列表项的初始选择.
  2. 当用户再次选择已选择的项目时,将忽略该项目.

现在我意识到,当你想到它时,它在旋转器上发生是有道理的- 它必须从选择的默认值开始,并且你只旋转它来改变那个值,而不是"重新选择"一个value - 文档实际上说:"仅当新选择的位置与先前选择的位置不同时才调用此回调".我已经看到答案表明你设置了一个标志来忽略第一个自动选择 - 我想我可以忍受,如果没有别的办法.

但是,因为我真正想要的是一个下拉列表,它应该作为一个下拉列表(并且用户可以并且应该期待),我需要的是 Spinner一样的行为就像一个下拉列表,就像一个组合-框.我不关心任何自动预选(这应该在没有触发我的听众的情况下发生),并且我想知道每个选择,即使它与之前的相同(毕竟,用户再次选择相同的项目) .

那么... Android中是否有可以做到这一点的东西,或者某些解决方法使Spinner表现得像下拉列表?如果这样的一个在这个网站,我还没有发现,并且具有满意的答案的问题,请让我知道(在这种情况下,我真诚地重复的问题道歉).

Fel*_*lix 8

大卫回答+1.但是,这是一个实现建议,不涉及从源代码复制粘贴代码(顺便说一下,它看起来与David 在2.3中发布的完全相同):

@Override
void setSelectionInt(int position, boolean animate) {
    mOldSelectedPosition = INVALID_POSITION;
    super.setSelectionInt(position, animate);
}
Run Code Online (Sandbox Code Playgroud)

这样你就可以欺骗父方法,让它每次都认为它是一个新的位置.

或者,您可以尝试在单击微调器并将其重新设置时将位置设置为无效onNothingSelected.这不是很好,因为用户在对话框启动时不会看到选择了哪个项目.


Amo*_*ter 5

好吧,我想在大卫和菲利克斯的回答的帮助下,我已经为自己的情况想出了一个解决方案(我相信大卫的帮助菲利克斯,后者反过来帮助我).我想我会在这里将它与代码示例一起发布,以防其他人发现这种方法也很有用.它还解决了我的两个问题(不需要的自动选择和所需的重新选择触发器).

我所做的是添加一个" 请选择 "虚拟项目作为我的列表中的第一项(最初只是为了解决自动选择问题,以便我可以忽略在没有用户交互的情况下选择它),然后,当另一个选择了项目,我已经处理了选择,我只是将微调器重置为虚拟项目(被忽略).想想看,在我决定在这个网站上发布我的问题之前我应该​​想到这一点,但事后总会更明显......我发现写我的问题实际上帮我思考了什么我想实现.

显然,如果有一个虚拟项目不适合你的情况,这可能不是你的理想解决方案,但因为我想要的是当用户选择一个值时触发一个动作(并且不需要保持选择值在我的具体情况下),这工作得很好.我将尝试添加一个简化的代码示例(可能无法按原样编译,我已经从我的工作代码中删除了一些内容并在粘贴前重命名了,但希望您能得到这个想法).

首先,包含微调器的列表活动(在我的例子中),我们称之为MyListActivity:

public class MyListActivity extends ListActivity {

    private Spinner mySpinner;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // TODO: other code as required...

        mySpinner = (Spinner) findViewById(R.id.mySpinner);
        mySpinner.setAdapter(new MySpinnerAdapter(this));
        mySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> aParentView,
                        View aView, int aPosition, long anId) {
                if (aPosition == 0) {
                    Log.d(getClass().getName(), "Ignoring selection of dummy list item...");
                } else {
                    Log.d(getClass().getName(), "Handling selection of actual list item...");
                    // TODO: insert code to handle selection
                    resetSelection();
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> anAdapterView) {
                // do nothing
            }
        });
    }

    /**
     * Reset the filter spinner selection to 0 - which is ignored in
     * onItemSelected() - so that a subsequent selection of another item is
     * triggered, regardless of whether it's the same item that was selected
     * previously.
     */
    protected void resetSelection() {
        Log.d(getClass().getName(), "Resetting selection to 0 (i.e. 'please select' item).");
        mySpinner.setSelection(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且微调器适配器代码看起来像这样(如果您愿意,实际上可能是上面列表活动中的内部类):

public class MySpinnerAdapter extends BaseAdapter implements SpinnerAdapter {

    private List<MyListItem> items; // replace MyListItem with your model object type
    private Context context;

    public MySpinnerAdapter(Context aContext) {
        context = aContext;
        items = new ArrayList<MyListItem>();
        items.add(null); // add first dummy item - selection of this will be ignored
        // TODO: add other items;
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public Object getItem(int aPosition) {
        return items.get(aPosition);
    }

    @Override
    public long getItemId(int aPosition) {
        return aPosition;
    }

    @Override
    public View getView(int aPosition, View aView, ViewGroup aParent) {
        TextView text = new TextView(context);
        if (aPosition == 0) {
            text.setText("-- Please select --"); // text for first dummy item
        } else {
            text.setText(items.get(aPosition).toString());
            // or use whatever model attribute you'd like displayed instead of toString()
        }
        return text;
    }
}
Run Code Online (Sandbox Code Playgroud)

我猜(没试过这个)可以用setSelected(false)相反的效果来实现相同的效果setSelection(0),但重新设置为"请选择"适合我的目的.并且,"看,马,没有旗帜!" (虽然我想忽略0选择并没有那么不同.)

希望这可以帮助其他人使用类似的用例.:-)对于其他用例,Felix的回答可能更合适(感谢Felix!).