我想使用一个微调器,最初(当用户还没有做出选择时)显示文本“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”也会作为第一项显示在下拉列表中,这不是我想要的。

我该如何解决这个问题?


当前回答

我找到了这个解决方案:

String[] items = new String[] {"Select 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);

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
        items[0] = "One";
        selectedItem = items[position];
    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
    }
});

只需用“Select One”更改数组[0],然后在onItemSelected中,将其重命名为“One”。

这不是一个很好的解决方案,但它是有效的

其他回答

我最终使用了Button。虽然Button不是旋转器,但其行为很容易自定义。

首先像往常一样创建适配器:

String[] items = new String[] {"One", "Two", "Three"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_spinner_dropdown_item, items);

注意,我使用simple_spinner_dropdown_item作为布局id。这将有助于创建一个更好的外观时,创建警报对话框。

在onClick处理我的按钮,我有:

public void onClick(View w) {
  new AlertDialog.Builder(this)
  .setTitle("the prompt")
  .setAdapter(adapter, new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {

      // TODO: user specific action

      dialog.dismiss();
    }
  }).create().show();
}

就是这样!

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

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

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

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

When extending SpinnerAdapter, you override two View-producing methods, getView(int, View, ViewGroup) and getDropDownView(int, View, ViewGroup). The first one supplies the View inserted into the Spinner itself; the second supplies the View in the drop-down list (as the name suggests). You can override the getView(...) so that, until an item has been selected, it displays a TextView containing a prompt; then, when you detect an item has been selected, you change it to display a TextView corresponding to that.

public class PromptingAdapter extends SpinnerAdapter {

    //... various code ...

    private boolean selectionmade = false;

    //call this method from the OnItemSelectedListener for your Spinner
    public setSelectionState(boolean b) {
        selectionmade = b;
    }

    @Override
    public View getView(int position, View recycle, ViewGroup container) {
        if(selectionmade) {
            //your existing code to supply a View for the Spinner
            //you could even put "return getDropDownView(position, recycle, container);"
        }
        else {
            View output;
            if(recycle instanceof TextView) {
                 output = recycle;
            }
            else {
                 output = new TextView();
                 //and layout stuff
            }
            output.setText(R.string.please_select_one);
            //put a string "please_select_one" in res/values/strings.xml
            return output;
        }
    }

//...
}

没有默认的API来设置微调提示。为了添加它,我们需要一个小的解决方案,而不是安全反射实现

List<Object> objects = new ArrayList<Object>();
objects.add(firstItem);
objects.add(secondItem);
// add hint as last item
objects.add(hint);

HintAdapter adapter = new HintAdapter(context, objects, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

Spinner spinnerFilmType = (Spinner) findViewById(R.id.spinner);
spinner.setAdapter(adapter);

// show hint
spinner.setSelection(adapter.getCount());

适配器来源:

public class HintAdapter
        extends ArrayAdapter<Objects> {

    public HintAdapter(Context theContext, List<Object> objects) {
        super(theContext, android.R.id.text1, android.R.id.text1, objects);
    }

    public HintAdapter(Context theContext, List<Object> objects, int theLayoutResId) {
        super(theContext, theLayoutResId, android.R.id.text1, objects);
    }

    @Override
    public int getCount() {
        // don't display last item. It is used as hint.
        int count = super.getCount();
        return count > 0 ? count - 1 : count;
    }
}

原始来源

最好的解决方案,我发现这实际上不是使用一个纺纱机,而是一个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上设置适配器。