我想使用一个微调器,最初(当用户还没有做出选择时)显示文本“Select One”。当用户单击微调器时,将显示项目列表,用户可以选择其中一个选项。用户做出选择后,所选项目将显示在微调器中,而不是“Select One”。

我有以下代码来创建一个旋转器:

String[] items = new String[] {"One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

使用这段代码,最初会显示项目“One”。我可以在项目中添加一个新项目“Select One”,但“Select One”也会作为第一项显示在下拉列表中,这不是我想要的。

我该如何解决这个问题?


当前回答

最好的解决方案,我发现这实际上不是使用一个纺纱机,而是一个AutoCompleteTextView。它基本上是一个带有附加Spinner的EditText,可以在你输入时显示建议-但是,通过正确的配置,它可以完全按照OP的要求进行操作。

XML:

<com.google.android.material.textfield.TextInputLayout
                android:id="@+id/item"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            <androidx.appcompat.widget.AppCompatAutoCompleteTextView
                    android:id="@+id/input"
                    android:hint="Select one"
                    style="@style/AutoCompleteTextViewDropDown"/>
        </com.google.android.material.textfield.TextInputLayout>

风格:

<style name="AutoCompleteTextViewDropDown">
    <item name="android:clickable">false</item>
    <item name="android:cursorVisible">false</item>
    <item name="android:focusable">false</item>
    <item name="android:focusableInTouchMode">false</item>
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">wrap_content</item>
</style>

至于适配器,使用基本的ArrayAdapter或扩展它来创建自己的适配器,但不需要在适配器方面进行额外的定制。在AutoCompleteTextView上设置适配器。

其他回答

看一下iosched应用程序,它提供了一个通用的解决方案,可以将元素添加到列表的顶部。特别是,如果您正在使用CursorAdapter,请查看TracksAdapter.java,它扩展了该定义以提供“setHasAllItem”方法和相关代码来管理列表计数,以处理顶部的额外项。

使用自定义适配器,您可以将文本设置为“Select One”或其他任何您希望顶部项目显示的内容。

考虑有N个项目要选择。

添加完这N个项目后,添加提示文本作为(N+1)个项目。

将所选项目设置为第N个位置[(N+1)个项目]。

在OnItemSelected Listener中,如果所选位置不是N,弹出最后一个项目并调用Adapter.notifyDataSetChanged()并将所选项目设置为所选位置。

就像这样:

    spinner.setItems("Daily", "One time", "Frequency"); // here "Frequency is the hint text"
    spinner.setSelectedIndex(2);

    spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
        @Override
        public void onItemSelected(Spinner view, int position, long id, Object item) {
            if (position != 2) {
                view.setItems("Daily", "One time");
                view.setSelectedIndex(position);
            }else {
                // This item is not a valid selection
            }
        }
    });

此代码已经过测试,在Android 4.4上工作

Spinner spinner = (Spinner) activity.findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, android.R.layout.simple_spinner_dropdown_item) {

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {

                View v = super.getView(position, convertView, parent);
                if (position == getCount()) {
                    ((TextView)v.findViewById(android.R.id.text1)).setText("");
                    ((TextView)v.findViewById(android.R.id.text1)).setHint(getItem(getCount())); //"Hint to be displayed"
                }

                return v;
            }       

            @Override
            public int getCount() {
                return super.getCount()-1; // you dont display last item. It is used as hint.
            }

        };

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        adapter.add("Daily");
        adapter.add("Two Days");
        adapter.add("Weekly");
        adapter.add("Monthly");
        adapter.add("Three Months");
        adapter.add("HINT_TEXT_HERE"); //This is the text that will be displayed as hint.


        spinner.setAdapter(adapter);
        spinner.setSelection(adapter.getCount()); //set the hint the default selection so it appears on launch.
        spinner.setOnItemSelectedListener(this);

如果你只有三个选择,我只会使用带有RadioButtons的RadioGroup,你可以在一开始让它们都未选中。

首先,您可能对Spinner类的prompt属性感兴趣。如下图所示,“Choose a Planet”是可以用android在XML中设置的提示符:prompt=""。

我建议子类化Spinner,在这里您可以在内部维护两个适配器。一个适配器有“选择一个”选项,另一个真正的适配器(有实际的选项),然后使用OnClickListener在选项对话框显示之前切换适配器。然而,在尝试实现这个想法后,我得出的结论是,你不能接收小部件本身的OnClick事件。

您可以将旋转器包装在不同的视图中,拦截视图上的单击,然后告诉CustomSpinner切换适配器,但这似乎是一种糟糕的hack。

你真的需要显示“选择一”吗?