我想使用一个微调器,最初(当用户还没有做出选择时)显示文本“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”也会作为第一项显示在下拉列表中,这不是我想要的。
我该如何解决这个问题?
之前提交的答案都没有真正按照我想要的方式解决这个问题。对我来说,理想的解决方案是在旋转器第一次显示时提供“Select One”(或任何初始文本)。当用户点击转轮时,初始文本不应该是显示的下拉框的一部分。
为了使我的特定情况更加复杂,我的旋转器数据来自通过LoaderManager回调加载的游标。
经过大量的实验,我想出了以下解决方案:
public class MyFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor>{
private static final String SPINNER_INIT_VALUE = "Select A Widget";
private Spinner mSpinner;
private int mSpinnerPosition;
private boolean mSpinnerDropDownShowing = false;
private View mSpinnerDropDown;
private MyCursorAdapter mCursorAdapter;
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
...
mCursorAdapter = new MyCursorAdapter(getActivity());
mSpinner = (Spinner) rootView.findViewById(R.id.theSpinner);
mSpinner.setOnTouchListener(mSpinnerTouchListener);
mSpinner.setAdapter(mCursorAdapter);
...
}
//Capture the touch events to toggle the spinner's dropdown visibility
private OnTouchListener mSpinnerTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(mSpinnerDropDown != null && mSpinnerDropDownShowing == false){
mSpinnerDropDownShowing = true;
mSpinnerDropDown.setVisibility(View.VISIBLE);
}
return false;
}
};
//Capture the click event on the spinner drop down items
protected OnClickListener spinnerItemClick = new OnClickListener(){
@Override
public void onClick(View view) {
String widget = ((TextView) view.findViewById(android.R.id.text1)).getText().toString();
if(!widget.equals(SPINNER_INIT_VALUE)){
if(mCursorAdapter != null){
Cursor cursor = mCursorAdapter.getCursor();
if(cursor.moveToFirst()){
while(!cursor.isAfterLast()){
if(widget.equals(cursor.getString(WidgetQuery.WIDGET_NAME))){
...
//Set the spinner to the correct item
mSpinnerPosition = cursor.getPosition() + 1;
mSpinner.setSelection(mSpinnerPosition);
break;
}
cursor.moveToNext();
}
}
}
}
//Hide the drop down. Not the most elegent solution but it is the only way I could hide/dismiss the drop down
mSpinnerDropDown = view.getRootView();
mSpinnerDropDownShowing = false;
mSpinnerDropDown.setVisibility(View.GONE);
}
};
private class MyCursorAdapter extends CursorAdapter {
private final int DISPLACEMENT = 1;
private final int DEFAULT_ITEM_ID = Integer.MAX_VALUE;
private Activity mActivity;
public MyCursorAdapter(Activity activity) {
super(activity, null, false);
mActivity = activity;
}
//When loading the regular views, inject the defualt item
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(position == 0){
if(convertView == null){
convertView = mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
}
return getDefaultItem(convertView);
}
return super.getView(position - DISPLACEMENT, convertView, parent);
}
//When loading the drop down views, set the onClickListener for each view
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent){
View view = super.getDropDownView(position, convertView, parent);
view.setOnClickListener(spinnerItemClick);
return view;
}
//The special default item that is being injected
private View getDefaultItem(View convertView){
TextView text = (TextView) convertView.findViewById(android.R.id.text1);
text.setText(SPINNER_INIT_VALUE);
return convertView;
}
@Override
public long getItemId(int position) {
if (position == 0) {
return DEFAULT_ITEM_ID;
}
return super.getItemId(position - DISPLACEMENT);
}
@Override
public boolean isEnabled(int position) {
return position == 0 ? true : super.isEnabled(position - DISPLACEMENT);
}
@Override
public int getViewTypeCount() {
return super.getViewTypeCount() + DISPLACEMENT;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return super.getViewTypeCount();
}
return super.getItemViewType(position - DISPLACEMENT);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor){
if(cursor.isAfterLast()){
return;
}
TextView text = (TextView) view.findViewById(android.R.id.text1);
String WidgetName = cursor.getString(WidgetQuery.WIDGET_NAME);
text.setText(WidgetName);
}
}
}
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;
}
}
//...
}
我找到了这个解决方案:
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”。
这不是一个很好的解决方案,但它是有效的
对我来说,它是这样工作的。有改进,只改变文本在某些选项,而不是全部。
首先,我采用旋转器的名称并创建带有自定义视图的arrayadapter,但现在这并不重要,关键是覆盖getView,并在内部更改你需要更改的值。在我的情况下只有第一个,其余的我离开原来的
public void rellenarSpinnerCompeticiones(){
spinnerArrayCompeticiones = new ArrayList<String>();
for(Competicion c: ((Controlador)getApplication()).getCompeticiones()){
spinnerArrayCompeticiones.add(c.getNombre());
}
//ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,R.layout.spinner_item_competicion,spinnerArrayCompeticiones);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, R.layout.spinner_item_competicion, spinnerArrayCompeticiones){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View v = vi.inflate(R.layout.spinner_item_competicion, null);
final TextView t = (TextView)v.findViewById(R.id.tvCompeticion);
if(spinnerCompeticion.getSelectedItemPosition()>0){
t.setText(spinnerArrayCompeticiones.get(spinnerCompeticion.getSelectedItemPosition()));
}else{
t.setText("Competiciones");
}
return v;
}
};
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerCompeticion.setAdapter(spinnerArrayAdapter);
}
没有默认的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;
}
}
原始来源
我通过使用按钮而不是旋转器来处理这个问题。我在GitHub上有样本项目。
在项目中,我同时显示旋转器和按钮,以显示它们确实看起来相同。除了按钮,你可以将初始文本设置为任何你想要的。
下面是活动的样子:
package com.stevebergamini.spinnerbutton;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Spinner;
public class MainActivity extends Activity {
Spinner spinner1;
Button button1;
AlertDialog ad;
String[] countries;
int selected = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner1 = (Spinner) findViewById(R.id.spinner1);
button1 = (Button) findViewById(R.id.button1);
countries = getResources().getStringArray(R.array.country_names);
// You can also use an adapter for the allert dialog if you'd like
// ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, countries);
ad = new AlertDialog.Builder(MainActivity.this).setSingleChoiceItems(countries, selected,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
button1.setText(countries[which]);
selected = which;
ad.dismiss();
}}).setTitle(R.string.select_country).create();
button1.setOnClickListener( new OnClickListener(){
@Override
public void onClick(View v) {
ad.getListView().setSelection(selected);
ad.show();
}});
}
}
注意:是的,我意识到这是依赖于应用的主题和外观将略有不同,如果使用Theme. holo。但是,如果您使用的是遗留主题之一,如Theme。黑色,你可以开始了。