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

我该如何解决这个问题?


当前回答

考虑有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
            }
        }
    });

其他回答

没有默认的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;
    }
}

原始来源

String[] listAges = getResources().getStringArray(R.array.ages);

        // Creating adapter for spinner
        ArrayAdapter<String> dataAdapter =
                new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, listAges);

        // Drop down layout style - list view with radio button
        dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        // attaching data adapter to spinner
        spinner_age.getBackground().setColorFilter(ContextCompat.getColor(this, R.color.spinner_icon), PorterDuff.Mode.SRC_ATOP);
        spinner_age.setAdapter(dataAdapter);
        spinner_age.setSelection(0);
        spinner_age.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String item = parent.getItemAtPosition(position).toString();

                if(position > 0){
                    // get spinner value
                    Toast.makeText(parent.getContext(), "Age..." + item, Toast.LENGTH_SHORT).show();
                }else{
                    // show toast select gender
                    Toast.makeText(parent.getContext(), "none" + item, Toast.LENGTH_SHORT).show();
                }
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

我得到了同样的问题旋转,与一个空的选择,我找到了一个更好的解决方案。看看这段简单的代码。

Spinner lCreditOrDebit = (Spinner)lCardPayView.findViewById(R.id.CARD_TYPE);
spinneradapter lAdapter = 
  new spinneradapter(
    BillPayScreen.this, 
    ndroid.R.layout.simple_spinner_item,getResources().getStringArray(R.array.creditordebit));
lAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
lCreditOrDebit.setAdapter(lAdapter);

这里spinneradapter是对arrayadapter的一个小定制。它是这样的:

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

public class spinneradapter extends ArrayAdapter<String>{
    private Context m_cContext;
    public spinneradapter(Context context,int textViewResourceId, String[] objects) {
        super(context, textViewResourceId, objects);
        this.m_cContext = context;
    }

    boolean firsttime = true;
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(firsttime){
            firsttime = false;
            //Just return some empty view
            return new ImageView(m_cContext);
        }
        //Let the array adapter take care of it this time.
        return super.getView(position, convertView, parent);
    }
}

如果您在从数据库游标填充项时遇到此问题,

我在这个SO答案中找到的最简单的解决方案:

在游标适配器查询中使用UNION,并将id= -1的附加项添加到查询结果中,而不真正将其添加到DB中:

喜欢的东西:

db.rawQuery("SELECT iWorkerId as _id, nvLastName as name  FROM  Worker
w  UNION  SELECT -1 as _id , '' as name",null);

如果选择的项目是-1,那么它是默认值。否则 这是桌子上的记录。

我昨天遇到了同样的问题,不想向ArrayAdapter添加隐藏项或使用反射,这工作得很好,但有点脏。

在阅读了许多帖子和尝试之后,我通过扩展ArrayAdapter和覆盖getView方法找到了一个解决方案。

import android.content.Context;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

/**
 * A SpinnerAdapter which does not show the value of the initial selection initially,
 * but an initialText.
 * To use the spinner with initial selection instead call notifyDataSetChanged().
 */
public class SpinnerAdapterWithInitialText<T> extends ArrayAdapter<T> {

    private Context context;
    private int resource;

    private boolean initialTextWasShown = false;
    private String initialText = "Please select";

    /**
     * Constructor
     *
     * @param context The current context.
     * @param resource The resource ID for a layout file containing a TextView to use when
     *                 instantiating views.
     * @param objects The objects to represent in the ListView.
     */
    public SpinnerAdapterWithInitialText(@NonNull Context context, int resource, @NonNull T[] objects) {
        super(context, resource, objects);
        this.context = context;
        this.resource = resource;
    }

    /**
     * Returns whether the user has selected a spinner item, or if still the initial text is shown.
     * @param spinner The spinner the SpinnerAdapterWithInitialText is assigned to.
     * @return true if the user has selected a spinner item, false if not.
     */
    public boolean selectionMade(Spinner spinner) {
        return !((TextView)spinner.getSelectedView()).getText().toString().equals(initialText);
    }

    /**
     * Returns a TextView with the initialText the first time getView is called.
     * So the Spinner has an initialText which does not represent the selected item.
     * To use the spinner with initial selection instead call notifyDataSetChanged(),
     * after assigning the SpinnerAdapterWithInitialText.
     */
    @Override
    public View getView(int position, View recycle, ViewGroup container) {
        if(initialTextWasShown) {
            return super.getView(position, recycle, container);
        } else {
            initialTextWasShown = true;
            LayoutInflater inflater = LayoutInflater.from(context);
            final View view = inflater.inflate(resource, container, false);

            ((TextView) view).setText(initialText);

            return view;
        }
    }
}

Android在初始化Spinner时所做的,是在为T[]对象中的所有项目调用getView之前为所选项目调用getView。 SpinnerAdapterWithInitialText在第一次调用时返回带有initialText的TextView。 其他时间都调用super。getView是ArrayAdapter的getView方法如果你正常使用Spinner,它会被调用。

要找出用户是否选择了一个微调项,或者微调器是否仍然显示initialText,请调用selectionMade并移交适配器分配给的微调器。