How to make an Android Spinner with initial text “Select One”?
我想使用一个微调器,该微调器最初(当用户尚未选择时)显示文本"选择一个"。 当用户单击微调器时,将显示项目列表,并且用户选择选项之一。 用户做出选择后,所选项目将显示在微调器中,而不是"选择一个"。
我有以下代码来创建一个微调器:
1 2 3 4 5 6 | 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); |
使用此代码,最初显示项目"一个"。 我可以在项目中添加一个新项目" Select One",但是" Select One"也将作为第一项显示在下拉列表中,这不是我想要的。
我该如何解决这个问题?
您可以做的是用
这是一个针对Android 2.3和4.0测试的工作示例(它在兼容性库中不使用任何东西,因此暂时可以使用)因为它是一个装饰器,应该很容易对现有代码进行改造,并且可以在
有一个Android错误,使得重新使用视图更加困难。 (因此,您必须使用
代码说明:2个构造函数
这使您可以使用标准提示或将您自己的"未选择内容"定义为第一行,或两者都定义,或不定义。 (注意:某些主题显示的是Spinner的DropDown而不是对话框。Dropdown通常不会显示提示)
您将布局定义为"看起来"像提示,例如,变灰...
使用标准提示(注意,未选择任何内容):
或带有提示和动态内容(也可能没有提示):
上例中的用法
1 2 3 4 5 6 7 8 9 10 11 | Spinner spinner = (Spinner) findViewById(R.id.spinner); ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.planets_array, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setPrompt("Select your favorite Planet!"); spinner.setAdapter( new NothingSelectedSpinnerAdapter( adapter, R.layout.contact_spinner_row_nothing_selected, // R.layout.contact_spinner_nothing_selected_dropdown, // Optional this)); |
contact_spinner_row_nothing_selected.xml
1 2 3 4 5 6 7 8 9 10 11 | <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/spinnerItemStyle" android:singleLine="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="marquee" android:textSize="18sp" android:textColor="#808080" android:text="[Select a Planet...]" /> |
NothingSelectedSpinnerAdapter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | import android.content.Context; import android.database.DataSetObserver; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListAdapter; import android.widget.SpinnerAdapter; /** * Decorator Adapter to allow a Spinner to show a 'Nothing Selected...' initially * displayed instead of the first choice in the Adapter. */ public class NothingSelectedSpinnerAdapter implements SpinnerAdapter, ListAdapter { protected static final int EXTRA = 1; protected SpinnerAdapter adapter; protected Context context; protected int nothingSelectedLayout; protected int nothingSelectedDropdownLayout; protected LayoutInflater layoutInflater; /** * Use this constructor to have NO 'Select One...' item, instead use * the standard prompt or nothing at all. * @param spinnerAdapter wrapped Adapter. * @param nothingSelectedLayout layout for nothing selected, perhaps * you want text grayed out like a prompt... * @param context */ public NothingSelectedSpinnerAdapter( SpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) { this(spinnerAdapter, nothingSelectedLayout, -1, context); } /** * Use this constructor to Define your 'Select One...' layout as the first * row in the returned choices. * If you do this, you probably don't want a prompt on your spinner or it'll * have two 'Select' rows. * @param spinnerAdapter wrapped Adapter. Should probably return false for isEnabled(0) * @param nothingSelectedLayout layout for nothing selected, perhaps you want * text grayed out like a prompt... * @param nothingSelectedDropdownLayout layout for your 'Select an Item...' in * the dropdown. * @param context */ public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) { this.adapter = spinnerAdapter; this.context = context; this.nothingSelectedLayout = nothingSelectedLayout; this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout; layoutInflater = LayoutInflater.from(context); } @Override public final View getView(int position, View convertView, ViewGroup parent) { // This provides the View for the Selected Item in the Spinner, not // the dropdown (unless dropdownView is not set). if (position == 0) { return getNothingSelectedView(parent); } return adapter.getView(position - EXTRA, null, parent); // Could re-use // the convertView if possible. } /** * View to show in Spinner with Nothing Selected * Override this to do something dynamic... e.g."37 Options Found" * @param parent * @return */ protected View getNothingSelectedView(ViewGroup parent) { return layoutInflater.inflate(nothingSelectedLayout, parent, false); } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 - // Spinner does not support multiple view types if (position == 0) { return nothingSelectedDropdownLayout == -1 ? new View(context) : getNothingSelectedDropdownView(parent); } // Could re-use the convertView if possible, use setTag... return adapter.getDropDownView(position - EXTRA, null, parent); } /** * Override this to do something dynamic... For example,"Pick your favorite * of these 37". * @param parent * @return */ protected View getNothingSelectedDropdownView(ViewGroup parent) { return layoutInflater.inflate(nothingSelectedDropdownLayout, parent, false); } @Override public int getCount() { int count = adapter.getCount(); return count == 0 ? 0 : count + EXTRA; } @Override public Object getItem(int position) { return position == 0 ? null : adapter.getItem(position - EXTRA); } @Override public int getItemViewType(int position) { return 0; } @Override public int getViewTypeCount() { return 1; } @Override public long getItemId(int position) { return position >= EXTRA ? adapter.getItemId(position - EXTRA) : position - EXTRA; } @Override public boolean hasStableIds() { return adapter.hasStableIds(); } @Override public boolean isEmpty() { return adapter.isEmpty(); } @Override public void registerDataSetObserver(DataSetObserver observer) { adapter.registerDataSetObserver(observer); } @Override public void unregisterDataSetObserver(DataSetObserver observer) { adapter.unregisterDataSetObserver(observer); } @Override public boolean areAllItemsEnabled() { return false; } @Override public boolean isEnabled(int position) { return position != 0; // Don't allow the 'nothing selected' // item to be picked. } } |
这是覆盖
这已经在Android 1.5至4.2上进行了测试,但请注意!由于此解决方案依赖于反射来调用专用的
通常我不会宽容这样的事情,但是这个问题已经被问了足够多次了,而且似乎是一个足够合理的请求,我以为我会发布解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | /** * A modified Spinner that doesn't automatically select the first entry in the list. * * Shows the prompt if nothing is selected. * * Limitations: does not display prompt if the entry list is empty. */ public class NoDefaultSpinner extends Spinner { public NoDefaultSpinner(Context context) { super(context); } public NoDefaultSpinner(Context context, AttributeSet attrs) { super(context, attrs); } public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void setAdapter(SpinnerAdapter orig ) { final SpinnerAdapter adapter = newProxy(orig); super.setAdapter(adapter); try { final Method m = AdapterView.class.getDeclaredMethod( "setNextSelectedPositionInt",int.class); m.setAccessible(true); m.invoke(this,-1); final Method n = AdapterView.class.getDeclaredMethod( "setSelectedPositionInt",int.class); n.setAccessible(true); n.invoke(this,-1); } catch( Exception e ) { throw new RuntimeException(e); } } protected SpinnerAdapter newProxy(SpinnerAdapter obj) { return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance( obj.getClass().getClassLoader(), new Class[]{SpinnerAdapter.class}, new SpinnerAdapterProxy(obj)); } /** * Intercepts getView() to display the prompt if position < 0 */ protected class SpinnerAdapterProxy implements InvocationHandler { protected SpinnerAdapter obj; protected Method getView; protected SpinnerAdapterProxy(SpinnerAdapter obj) { this.obj = obj; try { this.getView = SpinnerAdapter.class.getMethod( "getView",int.class,View.class,ViewGroup.class); } catch( Exception e ) { throw new RuntimeException(e); } } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { try { return m.equals(getView) && (Integer)(args[0])<0 ? getView((Integer)args[0],(View)args[1],(ViewGroup)args[2]) : m.invoke(obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } catch (Exception e) { throw new RuntimeException(e); } } protected View getView(int position, View convertView, ViewGroup parent) throws IllegalAccessException { if( position<0 ) { final TextView v = (TextView) ((LayoutInflater)getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE)).inflate( android.R.layout.simple_spinner_item,parent,false); v.setText(getPrompt()); return v; } return obj.getView(position,convertView,parent); } } } |
我最终改为使用
首先像往常一样创建适配器:
1 2 3 | String[] items = new String[] {"One","Two","Three"}; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, items); |
请注意,我使用
在我的Button的onClick处理程序中,我有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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(); } |
就是这样!
我知道这个问题有很多答案,但是我找到了最简单,最简单的方法。
此解决方案独立于API级别,适用于所有API级别。
想法是将微调框的最后一项设置为默认项。
1 | spinner.setSelection(lastIndex);//index starts from 0.so if spinner has 5 item the lastIndex is 4 |
最后一个索引的项目应为您的微调标题,例如"选择国家/地区"
并且在填充微调器时将项目数减少一个
// Count从1开始到总数。
1 2 3 4 5 6 | @Override public int getCount() { // don't display last item. It is used as hint. int count = super.getCount(); return count > 0 ? count - 1 : count; } |
所以你的代码流程将像这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | List<String> objects = new ArrayList<String>(); objects.add("India"); objects.add("Pakistan"); objects.add("China"); // add hint as last item objects.add("Select Country"); 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()); |
HintAdapter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class HintAdapter extends ArrayAdapter<Objects> { public HintAdapter(Context theContext, List<Object> objects, int theLayoutResId) { super(theContext, theLayoutResId, 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; } } |
微调标题
转盘项目
首先,您可能对
我打算建议子类化
您可以将微调框包裹在另一个视图中,拦截视图上的点击,然后告诉您
您真的需要显示"选择一个"吗?
此代码已经过测试,可在Android 4.4上运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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); |
我找到了这个解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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) { } }); |
只需使用"选择一个"更改array [0],然后在onItemSelected中将其重命名为"一个"。
不是经典的解决方案,但它可以工作:D
没有默认的API可在Spinner上设置提示。要添加它,我们需要一个小的解决方法,而不是不实施安全反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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()); |
适配器来源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } } |
原始资料
这里有很多答案,但令我惊讶的是,没有人提出一个简单的解决方案:将一个TextView放在Spinner顶部。在TextView上设置一个单击侦听器,该侦听器将隐藏TextView并显示Spinner,并调用spinner.performClick()。
对于旋转器,我遇到了同样的问题,选择了一个空的,我找到了一个更好的解决方案。看一下这个简单的代码。
1 2 3 4 5 6 7 | 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的一个小定制。看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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); } } |
您可以将其更改为"文本视图"并使用以下方法:
1 | android:style="@android:style/Widget.DeviceDefault.Light.Spinner" |
然后定义
XML档案:
1 2 3 4 | <Spinner android:id="@+id/locationSpinner" android:layout_width="fill_parent" android:layout_height="wrap_content" android:prompt="@string/select_location" /> |
活动:
1 2 3 | private Spinner featuresSelection; private ArrayAdapter<CharSequence> featuresAdapter; private List<CharSequence> featuresList; |
的onCreate:
1 2 3 4 5 6 7 8 9 10 | featuresList = new ArrayList<CharSequence>(); featuresAdapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, featuresList); featuresAdapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); featuresSelection = ((Spinner) yourActivity.this .findViewById(R.id.locationSpinner)); featuresSelection.setAdapter(featuresAdapter); featuresSelection.setOnItemSelectedListener( new MyOnItemSelectedListener()); |
一些功能(以编程方式将内容添加到适配器)>
1 | featuresAdapter.add("some string"); |
现在,您有一个空的微调器,可以编写代码以在未打开时不打开对话框。或者他们可以按回去。但是,您还可以在运行时使用函数或其他列表填充它。
这是我的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | List<String> list = new ArrayList<String>(); list.add("string1"); list.add("string2"); list.add("string3"); list.add("[Select one]"); final int listsize = list.size() - 1; ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list) { @Override public int getCount() { return(listsize); // Truncate the list } }; dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mySpinner.setAdapter(dataAdapter); mySpinner.setSelection(listsize); // Hidden item to appear in the spinner |
我已经尝试过以下方法。按下一个按钮,并为其提供click事件。通过更改按钮背景,它似乎是一个微调器。
声明为全局变量alertdialog和默认值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | AlertDialog d; static int default_value = 0; final Button btn = (Button) findViewById(R.id.button1); btn .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //c.show(); final CharSequence str[] = {"Android","Black Berry","Iphone"}; AlertDialog.Builder builder = new AlertDialog.Builder(TestGalleryActivity.this).setSingleChoiceItems( str, default_value,new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int position) { Toast.makeText(TestGalleryActivity.this, "" + position, Toast.LENGTH_SHORT).show(); default_value = position; btn.setText(str[position]); if(d.isShowing()) d.dismiss(); } }).setTitle("Select Any"); d = builder.create(); d.show(); } }); |
我的main.xml上有一个微调框,其ID为
这是我在OnCreate函数中写的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | spinner1 = (Spinner)this.findViewById(R.id.spinner1); final String[] groupes = new String[] {"A","B","C","D","E","F","G","H"}; ArrayAdapter<CharSequence> featuresAdapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, new ArrayList<CharSequence>()); featuresAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner1.setAdapter(featuresAdapter); for (String s : groupes) featuresAdapter.add(s); spinner1.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView< ? > arg0, View arg1, int position, long id) { // Here go your instructions when the user chose something Toast.makeText(getBaseContext(), groupes[position], 0).show(); } public void onNothingSelected(AdapterView< ? > arg0) { } }); |
它在类中不需要任何实现。
查看iosched应??用程序,这是将元素添加到列表顶部的通用解决方案。特别是,如果您使用的是CursorAdapter,请查看TracksAdapter.java,它将定义扩展为提供" setHasAllItem"方法和相关代码,以管理列表数以处理顶部的额外项目。
使用自定义适配器,您可以将文本设置为"选择一个",也可以将其设置为其他内容。
我为此找到了许多好的解决方案。大多数方法是通过在适配器的末尾添加一个项目来实现的,并且不显示下拉列表中的最后一个项目。
对我来说,最大的问题是微调框下拉列表将从列表底部开始。因此,在第一次触摸微调器之后,用户看到的是最后一个项目,而不是第一个项目(如果要显示的项目很多)。
因此,我将提示项放在列表的开头。并在下拉列表中隐藏第一项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | private void loadSpinner(){ HintArrayAdapter hintAdapter = new HintArrayAdapter<String>(context, 0); hintAdapter.add("Hint to be displayed"); hintAdapter.add("Item 1"); hintAdapter.add("Item 2"); . . hintAdapter.add("Item 30"); spinner1.setAdapter(hintAdapter); //spinner1.setSelection(0); //display hint. Actually you can ignore it, because the default is already 0 //spinner1.setSelection(0, false); //use this if don't want to onItemClick called for the hint spinner1.setOnItemSelectedListener(yourListener); } private class HintArrayAdapter< T > extends ArrayAdapter< T > { Context mContext; public HintArrayAdapter(Context context, int resource) { super(context, resource); this.mContext = context } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(android.R.layout.simple_spinner_item, parent, false); TextView texview = (TextView) view.findViewById(android.R.id.text1); if(position == 0) { texview.setText(""); texview.setHint(getItem(position).toString()); //"Hint to be displayed" } else { texview.setText(getItem(position).toString()); } return view; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); View view; if(position == 0){ view = inflater.inflate(R.layout.spinner_hint_list_item_layout, parent, false); // Hide first row } else { view = inflater.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false); TextView texview = (TextView) view.findViewById(android.R.id.text1); texview.setText(getItem(position).toString()); } return view; } } |
当position为0时,在@Override getDropDownView()中设置以下布局,以隐藏第一条提示行。
R.layout.spinner_hint_list_item_layout:
1 2 3 4 5 6 7 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content"> </LinearLayout> |
所以这是我最后的例子,一个按钮旋转的"全押"
在activity_my_form.xml中
1 2 3 4 5 6 7 8 9 10 | <Button android:id="@+id/btnSpinnerPlanets" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="left|center_vertical" android:singleLine="true" android:text="@string/selectAPlanet" android:textSize="10sp" android:background="@android:drawable/btn_dropdown"> </Button> |
在strings.xml中
1 2 3 4 5 6 7 8 9 10 11 12 13 | <string name="selectAPlanet">Select planet…</string> <string-array name="planets__entries"> <item>The Sun with a name very long so long long long long longThe Sun with a name very long so long long long long longThe Sun with a name very long so long long long long long</item> <item>Mercury</item> <item>Venus</item> <item>Earth</item> <item>Mars</item> <item>Jupiter</item> <item>Saturn</item> <item>Uranus</item> <item>Neptune</item> </string-array> |
在MyFormActivity.java中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class MyFormActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { ((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { final String[] items = view.getResources().getStringArray(R.array.planets__entries); ArrayAdapter<String> adapter = new ArrayAdapter<String>(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items); new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(adapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ((Button) findViewById(R.id.btnSpinnerPlanets)).setText(items[which]); dialog.dismiss(); } }).create().show(); } }); } } |
最终,我获得了可配置的字体大小,没有第一项可选按钮微调器!!!
感谢HRJ
我认为最简单的方法是在索引0上创建一个虚拟项目,说"选择一个",然后在保存时检查选择项是否为0。
此外,还有一个简单的技巧可以显示默认值:
您可以在列表中添加默认值,然后使用
这里的示例可行代码:
1 2 3 4 5 6 | List<FuelName> fuelList = new ArrayList<FuelName>(); fuelList.add(new FuelName(0,"Select One")); fuelList.addAll(response.body()); ArrayAdapter adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, fuelList); //fuelName.setPrompt("Select Fuel"); fuelName.setAdapter(adapter); |
希望它能恢复您的复杂性。编码愉快!
对于使用Xamarin的用户,这里的C#等效于上述aaronvargas的答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | using Android.Content; using Android.Database; using Android.Views; using Android.Widget; using Java.Lang; namespace MyNamespace.Droid { public class NothingSelectedSpinnerAdapter : BaseAdapter, ISpinnerAdapter, IListAdapter { protected static readonly int EXTRA = 1; protected ISpinnerAdapter adapter; protected Context context; protected int nothingSelectedLayout; protected int nothingSelectedDropdownLayout; protected LayoutInflater layoutInflater; public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) : this(spinnerAdapter, nothingSelectedLayout, -1, context) { } public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) { this.adapter = spinnerAdapter; this.context = context; this.nothingSelectedLayout = nothingSelectedLayout; this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout; layoutInflater = LayoutInflater.From(context); } protected View GetNothingSelectedView(ViewGroup parent) { return layoutInflater.Inflate(nothingSelectedLayout, parent, false); } protected View GetNothingSelectedDropdownView(ViewGroup parent) { return layoutInflater.Inflate(nothingSelectedDropdownLayout, parent, false); } public override Object GetItem(int position) { return position == 0 ? null : adapter.GetItem(position - EXTRA); } public override long GetItemId(int position) { return position >= EXTRA ? adapter.GetItemId(position - EXTRA) : position - EXTRA; } public override View GetView(int position, View convertView, ViewGroup parent) { // This provides the View for the Selected Item in the Spinner, not // the dropdown (unless dropdownView is not set). if (position == 0) { return GetNothingSelectedView(parent); } // Could re-use the convertView if possible. return this.adapter.GetView(position - EXTRA, null, parent); } public override int Count { get { int count = this.adapter.Count; return count == 0 ? 0 : count + EXTRA; } } public override View GetDropDownView(int position, View convertView, ViewGroup parent) { // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 - // Spinner does not support multiple view types if (position == 0) { return nothingSelectedDropdownLayout == -1 ? new View(context) : GetNothingSelectedDropdownView(parent); } // Could re-use the convertView if possible, use setTag... return adapter.GetDropDownView(position - EXTRA, null, parent); } public override int GetItemViewType(int position) { return 0; } public override int ViewTypeCount => 1; public override bool HasStableIds => this.adapter.HasStableIds; public override bool IsEmpty => this.adapter.IsEmpty; public override void RegisterDataSetObserver(DataSetObserver observer) { adapter.RegisterDataSetObserver(observer); } public override void UnregisterDataSetObserver(DataSetObserver observer) { adapter.UnregisterDataSetObserver(observer); } public override bool AreAllItemsEnabled() { return false; } public override bool IsEnabled(int position) { return position > 0; } } } |
扩展
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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; } } //... } |
我还通过使用以下代码解决了此问题。假设您有一个项目列表,例如
1 2 3 4 5 6 7 8 9 | ArrayList<Item> itemsArrayList = new ArrayList<Item>(); Item item1 = new Item(); item1.setId(1); item1.setData("First Element"); Item item2 = new Item(); item2.setId(2); Item2.setData("Second Element"); itemsArrayList.add(item1); itemsArrayList.add(item2); |
现在,我们必须将字符串提供给Spinner,因为Spinner无法理解对象。因此,我们将使用这样的字符串项创建一个新的数组列表->
1 2 3 4 | ArrayList<String> itemStringArrayList = new ArrayList<String>(); for(Item item : itemsArrayList) { itemStringArrayList.add(item.getData()); } |
现在,我们有了带有两个字符串项的
1 | itemStringArrayList.add("Select Item"); |
现在我们有了一个数组列表
因此,我们可以像这样实现此功能。如果您需要将数组列表项加载到android微调器中。因此,您将不得不使用一些适配器。因此,在这里我将使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ArrayAdapter<String> itemsArrayAdapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.spinner_item, itemsArrayList){ @Override public boolean isEnabled(int position) { if(position == 0) { return false; } else { return true; } } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View view = super.getDropDownView(position, convertView, parent); TextView tv = (TextView) view; if(position == 0){ // Set the hint text color gray tv.setTextColor(Color.GRAY); } else { tv.setTextColor(Color.BLACK); } return view; } }; itemsArrayAdapter.setDropDownViewResource(R.layout.spinner_item); your_spinner_name.setAdapter(itemsArrayAdapter); |
在此代码中。我们正在使用自定义的微调器布局,即
1 2 3 4 5 6 7 8 9 | <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:textStyle="italic" android:fontFamily="sans-serif-medium" /> |
我们需要禁用微调器中的第一个文本。因此,对于位置0,我们禁用文本。我们也可以通过覆盖getDropDownView方法来设置颜色。因此,通过这种方式,我们将获得预期的微调器。
如果您只有三个选择,我只会将RadioGroup与RadioButtons一起使用,可以先将它们全部取消选中。
以前提交的答案中没有一个能真正解决我想解决的问题。对我而言,理想的解决方案是在初次显示微调框时提供"选择一个"(或任何初始文本)。当用户点击微调器时,初始文本不应成为显示的下拉菜单的一部分。
为了使我的情况更加复杂,我的微调器数据来自一个游标,该游标是通过LoaderManager回调加载的。
经过大量的实验,我提出了以下解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | 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); } } } |
我通过使用按钮而不是微调按钮来处理此问题。我在GitHub上有示例项目。
在项目中,我同时显示了微调器和按钮,以表明它们确实看起来完全相同。除了按钮,您还可以将初始文本设置为所需的任何内容。
活动如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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.Black)之一,那就很好了。
如果从数据库游标填充项目时遇到此问题,
我在这个答案中找到的最简单的解决方案:
在游标适配器查询中使用UNION并将id = -1的其他项添加到查询结果中,而无需真正将其添加到数据库中:
就像是:
db.rawQuery("SELECT iWorkerId as _id, nvLastName as name FROM Worker
w UNION SELECT -1 as _id , '' as name",null);
如果所选项目为-1,则为默认值。除此以外
这是表中的记录。
我为此找到的最佳解决方案实际上是不使用微调器,而是使用AutoCompleteTextView。它基本上是一个EditText,带有附加的Spinner,可以在您键入时显示建议-但是,使用正确的配置,它的行为可以完全符合OP的要求以及更多。
XML:
1 2 3 4 5 6 7 8 9 10 | <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> |
样式:
1 2 3 4 5 6 7 8 | <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上设置适配器。
对我来说,它像这样工作。有了改进,仅更改了某些选项中的文本,而不是全部。
首先,我使用微调器的名称并使用自定义视图创建arrayadapter,但是现在不重要了,关键是覆盖getView,然后在内部更改您需要更改的值。就我而言,这只是第一个,其余的我离开了原来的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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); } |
这是一个简单的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | private boolean isFirst = true; private void setAdapter() { final ArrayList<String> spinnerArray = new ArrayList<String>(); spinnerArray.add("Select your option"); spinnerArray.add("Option 1"); spinnerArray.add("Option 2"); spin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView< ? > parentView, View selectedItemView, int position, long id) { TextView tv = (TextView)selectedItemView; String res = tv.getText().toString().trim(); if (res.equals("Option 1")) { //do Something } else if (res.equals("Option 2")) { //do Something else } } @Override public void onNothingSelected(AdapterView< ? > parentView) { } }); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.my_spinner_style,spinnerArray) { public View getView(int position, View convertView, ViewGroup parent) { View v = super.getView(position, convertView, parent); int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics()); ((TextView) v).setTypeface(tf2); ((TextView) v).getLayoutParams().height = height; ((TextView) v).setGravity(Gravity.CENTER); ((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, 19); ((TextView) v).setTextColor(Color.WHITE); return v; } public View getDropDownView(int position, View convertView, ViewGroup parent) { if (isFirst) { isFirst = false; spinnerArray.remove(0); } View v = super.getDropDownView(position, convertView, parent); ((TextView) v).setTextColor(Color.argb(255, 70, 70, 70)); ((TextView) v).setTypeface(tf2); ((TextView) v).setGravity(Gravity.CENTER); return v; } }; spin.setAdapter(adapter); } |
请参阅以上答案之一:https://stackoverflow.com/a/23005376/1312796
我添加了代码以修复一个小错误。那没有数据检索..如何显示提示文本..!
这是我的把戏...对我来说很好用。 !
尝试将微调器放在Relative_layout中,并在微调器的适配器加载或变空时将Textview与微调器对齐,并使用Textview的可见性(SHOW / HIDE)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="20dp" android:background="#ededed" android:orientation="vertical"> <TextView android:id="@+id/txt_prompt_from" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:textColor="@color/gray" android:textSize="16sp" android:layout_alignStart="@+id/sp_from" android:text="From" android:visibility="gone"/> <Spinner android:id="@+id/sp_from" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" /> |
这是代码:
1 | txt__from = (TextView) rootView.findViewById(R.id.txt_prompt_from); |
在旋转器适配器加载和清空之前和之后调用此方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | setPromptTextViewVisibility (); //True or fales public void setPromptTextViewVisibility (boolean visible ) { if (visible) { txt_from.setVisibility(View.VISIBLE); } else { txt_from.setVisibility(View.INVISIBLE); } } |
使其变得像这样简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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) { } }); |
昨天我遇到了同样的问题,不想将隐藏项添加到ArrayAdapter或使用反射,这种方法可以正常工作,但有点脏。
阅读许多文章并进行尝试之后,我发现了通过扩展
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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; } } } |
初始化Spinner时Android会执行的操作是,在
所有其他时间,它都调用
若要确定用户是否选择了微调器项目,或者微调器是否仍显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public AdapterView.OnItemSelectedListener instructorSpinnerListener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView << ? > adapterView, View view, int i, long l) { String selectedInstructorName = adapterView.getItemAtPosition(i).toString(); if (selectedInstructorName.equals("[Select Instructor]")) { instructorSpinnerAdapter.clear(); for (Offering offering: allOfferingsList) instructorSpinnerAdapter.add(offering); } else { instructorSpinnerAdapter.clear(); } } @Override public void onNothingSelected(AdapterView<< ? > adapterView) { adapterView.setSelection(0); // Toast.makeText(getApplicationContext(),"Why?", Toast.LENGTH_SHORT).show(); } }; |
似乎是一个过时的解决方案,但我通常只是在微调框的前面放置一个TextView。整个Xml看起来像这样。 (嗨,伙计们,别开枪我,我知道你们中有些人不喜欢这种婚姻):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <FrameLayout android:id="@+id/selectTypesLinear" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <Spinner android:id="@+id/spinnerExercises" android:layout_width="match_parent" android:layout_height="match_parent" android:entries="@array/exercise_spinner_entries" android:prompt="@string/exercise_spinner_prompt" /> <TextView android:id="@+id/spinnerSelectText" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Hey! Select this guy!" android:gravity="center" android:background="#FF000000" /> </FrameLayout> |
然后,当选择一个项目时,我将隐藏TextView。显然,TextView的背景色应与Spinner相同。适用于Android 4.0。不知道较旧的版本。
是。因为Spinner在开始时调用setOnItemSelectedListener,所以textview的隐藏可能会有些棘手,但是可以通过以下方式完成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | Boolean controlTouched; exerciseSpinner.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { controlTouched = true; // I touched it but but not yet selected an Item. return false; } }); exerciseSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView< ? > arg0, View arg1, int arg2, long arg3) { if (controlTouched) { // Are you sure that I touched it with my fingers and not someone else ? spinnerSelText.setVisibility(View.GONE); } } @Override public void onNothingSelected(AdapterView< ? > arg0) { } }); |
考虑有N个项目可供选择。
添加这N个项目后,将提示文本添加为??第(N + 1)个项目。
将所选项目设置在第N个位置[第(N + 1)个项目]。
在您的OnItemSelected侦听器中,如果所选位置不是N,则弹出最后一个项目并调用Adapter.notifyDataSetChanged()并将所选项目设置为所选位置。
像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 } } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ArrayList<String> sizes = new ArrayList<>(); spinner = (Spinner) findViewById(R.id.spinner_size); if (sizes != null && !sizes.isEmpty()) { //SORT ArrayList If You Want Data in ASC or DSC Order sizes.add("28"); sizes.add("29"); sizes.add("31"); sizes.add("Choose Size"); //adding String at the end of ArrayList Collections.reverse(sizes); //Last Item Will Be Shown As A Spinner Title ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, sizes); spinner.setAdapter(adapter); |
只需使用arraylist.add(" Your Data")方法在arrayList的末尾添加项目,然后使用Collection.reverse(arrayList)对其进行反转,以使Title成为Spinner中的第一项。您还可以在最后添加数据之前对项目进行排序。