Pie*_*ers 554 android android-spinner
在Android中,我想使用Spinner(当用户尚未进行选择时)显示文本"Select One".当用户单击微调器时,将显示项目列表,并且用户选择其中一个选项.用户进行选择后,所选项目将显示在微调器中,而不是"选择一个".
我有以下代码来创建一个Spinner:
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);
Run Code Online (Sandbox Code Playgroud)
使用此代码,最初显示项目"One".我可以在项目中添加一个新项目"Select One",但是"Select One"也会在下拉列表中显示为第一项,这不是我想要的.
我该如何解决这个问题?
aar*_*gas 283
您可以做的是SpinnerAdapter用一个呈现"选择选项..."的装饰来装饰您最初为Spinner显示没有选择的内容.
这是一个针对Android 2.3和4.0进行测试的工作示例(它在兼容性库中没有使用任何内容,因此它应该可以使用一段时间)因为它是装饰器,所以应该很容易改进现有代码并且它也可以正常工作CursorLoader.(交换光标在包裹cursorAdapter当然...)
有一个Android错误使重新使用视图变得更加困难.(所以你必须使用setTag或其他东西来确保你convertView的正确.)Spinner不支持多种视图类型
代码注释:2个构造函数
这允许您使用标准提示或将您自己的"未选择"定义为第一行或两者,或者无.(注意:某些主题显示Spinner的DropDown而不是对话框.Dropdown通常不显示提示)
您可以将布局定义为"看起来"像提示,例如,灰显...

使用标准提示(注意没有选择任何内容):

或者提示和动态的东西(也可能没有提示):

用于以上示例
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));
Run Code Online (Sandbox Code Playgroud)
contact_spinner_row_nothing_selected.xml
<?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...]" />
Run Code Online (Sandbox Code Playgroud)
NothingSelectedSpinnerAdapter.java
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.
}
}
Run Code Online (Sandbox Code Playgroud)
emm*_*mby 251
这是一个覆盖Spinner视图的通用解决方案.它会覆盖setAdapter()将初始位置设置为-1,并代理提供的SpinnerAdapter以显示小于0的位置的提示字符串.
这已经在Android 1.5到4.2上进行了测试,但买家要小心!由于这种解决方案依赖于反射调用私有AdapterView.setNextSelectedPositionInt()和AdapterView.setSelectedPositionInt(),它不能保证在未来的操作系统的更新工作.它似乎很可能,但它绝不是保证.
Normally I wouldn't condone something like this, but this question has been asked enough times and it seems like a reasonable enough request that I thought I would post my solution.
/**
* 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
HRJ*_*HRJ 129
我最终用了一个Button代替.虽然a Button不是a Spinner,但行为很容易定制.
首先像往常一样创建适配器:
String[] items = new String[] {"One", "Two", "Three"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, items);
Run Code Online (Sandbox Code Playgroud)
请注意,我使用的simple_spinner_dropdown_item是布局ID.这有助于在创建警报对话框时创建更好的外观.
在我的Button的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();
}
Run Code Online (Sandbox Code Playgroud)
就是这样!
Sha*_*yaz 111
我知道这个问题有很多答案,但我找到了最简单,最简单的方法.
此解决方案独立于API级别,它适用于所有API级别.
想法是将微调器的最后一项设置为默认值
spinner.setSelection(lastIndex);//index starts from 0.so if spinner has 5 item the lastIndex is 4
Run Code Online (Sandbox Code Playgroud)
最后一个索引的项目应该是您的微调器标题,如"选择国家/地区"
在填充微调器时,将项目数减少一个.计数从1开始计数到总项目.
@Override
public int getCount() {
// don't display last item. It is used as hint.
int count = super.getCount();
return count > 0 ? count - 1 : count;
}
Run Code Online (Sandbox Code Playgroud)
所以你的代码流将是这样的
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());
Run Code Online (Sandbox Code Playgroud)
HintAdapter.java
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;
}
}
Run Code Online (Sandbox Code Playgroud)
微调标题
旋转器项目
Cas*_*sey 66
首先,您可能prompt对该Spinner类的属性感兴趣.请参见下图,"选择一个星球"是可以在XML中设置的提示 android:prompt="".
我打算建议子类化Spinner,你可以在内部维护两个适配器.一个具有"Select One"选项的适配器和另一个真正的适配器(具有实际选项),然后使用OnClickListener在显示选择对话框之前切换适配器.然而,在尝试实现这个想法后,我得出结论,你不能接收OnClick小部件本身的事件.
您可以将微调器包装在不同的视图中,拦截视图上的点击,然后告诉您CustomSpinner切换适配器,但看起来像是一个糟糕的黑客.
你真的需要展示"选择一个"吗?
Man*_*nos 57
此代码已经过测试,适用于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);
Run Code Online (Sandbox Code Playgroud)
小智 31
我找到了这个解决方案
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) {
}
});
Run Code Online (Sandbox Code Playgroud)
只需使用"Select One"更改数组[0],然后在onItemSelected中将其重命名为"One".
不是一个优雅的解决方案,但它的工作原理:D
Yak*_*pan 20
没有默认API可以在Spinner上设置提示.要添加它,我们需要一个小的解决方法,而不是安全反射实现
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());
Run Code Online (Sandbox Code Playgroud)
适配器来源:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
mja*_*ola 17
这里有很多答案,但我很惊讶没有人建议一个简单的解决方案:在Spinner上放置一个TextView.在TextView上设置一个单击监听器,隐藏TextView显示Spinner,并调用spinner.performClick().
小智 9
我对旋转器有同样的问题,选择空了,我找到了更好的解决方案.看看这个简单的代码.
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);
Run Code Online (Sandbox Code Playgroud)
这里的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);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将其更改为文本视图并使用此:
android:style="@android:style/Widget.DeviceDefault.Light.Spinner"
Run Code Online (Sandbox Code Playgroud)
然后定义android:text属性.
这是我的方式:
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
Run Code Online (Sandbox Code Playgroud)
XML文件:
<Spinner android:id="@+id/locationSpinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="@string/select_location" />
Run Code Online (Sandbox Code Playgroud)
活动:
private Spinner featuresSelection;
private ArrayAdapter<CharSequence> featuresAdapter;
private List<CharSequence> featuresList;
Run Code Online (Sandbox Code Playgroud)
的onCreate:
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());
Run Code Online (Sandbox Code Playgroud)
一些功能(以编程方式向适配器添加内容)>
featuresAdapter.add("some string");
Run Code Online (Sandbox Code Playgroud)
现在您有一个空的微调器,如果为空,您可以编写代码以不打开对话框.或者他们可以回压.但是,您还可以在运行时使用函数或其他列表填充它.
另外,还有一个简单的技巧来显示默认值:
您可以在列表中添加默认值,然后使用以下命令添加所有集合list.addAll(yourCollection);
这里的示例可行代码:
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);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
516433 次 |
| 最近记录: |