我想使用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);
使用此代码,最初显示项目“One”。我可以在项目中添加一个新项目“Select One”,但是“Select One”也会在下拉列表中显示为第一项,这不是我想要的。
如何解决此问题?
答案 0 :(得分:279)
你可以做的是装饰你的SpinnerAdapter
,其中一个呈现'选择选项......'最初查看旋转器以显示没有选择。
这是一个针对Android 2.3和4.0进行测试的工作示例(它在兼容性库中没有使用任何内容,因此它应该可以使用一段时间)因为它是装饰器,所以应该很容易改进现有代码并且它可以正常工作CursorLoader
也是。 (当然,在包裹的cursorAdapter
上交换光标...)
有一个Android错误使重新使用视图变得更加困难。 (因此,您必须使用setTag
或其他内容来确保convertView
正确无误。)Spinner does not support multiple view types
代码注释: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));
<强> 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...]" />
<强> 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.
}
}
答案 1 :(得分:247)
这是覆盖Spinner
视图的一般解决方案。它会覆盖setAdapter()
以将初始位置设置为-1,并代理提供的SpinnerAdapter
以显示小于0的位置的提示字符串。
这已在Android 1.5到4.2上测试过,但买家要小心!由于此解决方案依赖于反射来调用私有AdapterView.setNextSelectedPositionInt()
和AdapterView.setSelectedPositionInt()
,因此无法保证在将来的操作系统更新中工作。它似乎很可能,但它绝不是保证。
通常情况下,我不会宽恕这样的事情,但这个问题已经被问到了足够多次,这似乎是一个合理的请求,我认为我会发布我的解决方案。
/**
* 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);
}
}
}
答案 2 :(得分:126)
我最终使用的是Button
。虽然Button
不是Spinner
,但行为很容易自定义。
首先像往常一样创建适配器:
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。这有助于在创建警报对话框时创建更好的外观。
在我的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();
}
就是这样!
答案 3 :(得分:105)
我知道这个问题有很多答案,但我找到了最简单,最简单的方法。
This solution独立于API级别,适用于所有API级别。
想法是将微调器的最后一项设置为默认值..IE
spinner.setSelection(lastIndex);//index starts from 0.so if spinner has 5 item the lastIndex is 4
最后一个索引处的项目应该是您的微调器标题,如“选择国家/地区”
在填充微调器时,将项目数减少一个 //计数从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;
}
所以你的代码流将是这样的
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
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;
}
}
Spinner Title
Spinner Item
答案 4 :(得分:66)
首先,您可能对prompt
类的Spinner
属性感兴趣。请参见下图,“选择一个星球”是可以使用android:prompt=""
在XML中设置的提示。
我打算建议继承Spinner
,你可以在内部维护两个适配器。一个具有“Select One”选项的适配器和另一个 real 适配器(具有实际选项),然后使用OnClickListener
在显示选择对话框之前切换适配器。但是,在尝试实现该想法后,我得出结论,您无法接收小部件本身的OnClick
事件。
您可以将微调器包装在不同的视图中,拦截视图上的点击,然后告诉您的CustomSpinner
切换适配器,但看起来非常糟糕。
你真的需要展示“选择一个”吗?
答案 5 :(得分:55)
此代码已经过测试,适用于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);
答案 6 :(得分:30)
我找到了这个解决方案:
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”。
不是一个优雅的解决方案,但它有效:D
答案 7 :(得分: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());
适配器来源:
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;
}
}
答案 8 :(得分:13)
这里有很多答案,但我很惊讶没有人建议一个简单的解决方案:在Spinner上放置一个TextView。在TextView上设置一个单击监听器,隐藏TextView显示Spinner,并调用spinner.performClick()。
答案 9 :(得分: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);
这里的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);
}
}
答案 10 :(得分:6)
XML文件:
<Spinner android:id="@+id/locationSpinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="@string/select_location" />
的活动:
private Spinner featuresSelection;
private ArrayAdapter<CharSequence> featuresAdapter;
private List<CharSequence> featuresList;
的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());
某些功能(以编程方式向适配器添加内容)&gt;
featuresAdapter.add("some string");
现在您有一个空的微调器,如果为空,您可以编写代码以不打开对话框。或者他们可以回压。但是,您还可以在运行时使用函数或其他列表填充它。
答案 11 :(得分:6)
您可以将其更改为文本视图并使用它:
android:style="@android:style/Widget.DeviceDefault.Light.Spinner"
然后定义android:text
属性。
答案 12 :(得分:4)
我尝试过如下。单击按钮并将click事件发送给它。通过更改按钮背景,它似乎是一个微调器。
声明为全局变量alertdialog和默认值..
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();
}
});
答案 13 :(得分:4)
这是我的方式:
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
答案 14 :(得分:3)
我的main.xml上有一个微调器,其id为@+id/spinner1
这是我在OnCreate函数中写的:
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) { }
});
在课堂上不需要任何实现。
答案 15 :(得分:3)
查看iosched应用程序,了解将元素添加到列表顶部的通用解决方案。特别是,如果您使用的是CursorAdapter,请查看扩展该定义的TracksAdapter.java以提供“setHasAllItem”方法和相关代码来管理列表计数以处理顶部的额外项目。
使用自定义适配器,您可以将文本设置为“选择一个”或您可能希望该顶级项目说出的任何其他内容。
答案 16 :(得分:2)
我找到了很多很好的解决方案。大多数是通过在适配器的末尾添加项目,并且不显示下拉列表中的最后一项。 对我来说最大的问题是微调器下拉列表将从列表的底部开始。因此,用户在第一次触摸微调器后,会看到最后一项而不是第一项(如果要显示很多项)。
所以我把提示项放到列表的开头。并隐藏下拉列表中的第一项。
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;
}
}
当位置为0时,在@Override getDropDownView()中设置以下布局,以隐藏第一个提示行。
R.layout.spinner_hint_list_item_layout:
<?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>
答案 17 :(得分:2)
所以这是我对按钮微调器
的最后一个例子“all-in”在 activity_my_form.xml
中 <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
中<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
中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
答案 18 :(得分:2)
我认为最简单的方法是在索引0上创建一个虚拟项目,说“选择一个”,然后在保存时可以检查选择是否为0。
答案 19 :(得分:1)
我还使用以下代码解决了这个问题。假设您有一个项目列表,例如
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无法理解该对象。因此,我们将创建一个包含此类字符串项的新数组列表 - &gt;
ArrayList<String> itemStringArrayList = new ArrayList<String>();
for(Item item : itemsArrayList) {
itemStringArrayList.add(item.getData());
}
现在我们有itemStringArrayList
数组列表,其中包含两个字符串项。我们必须展示&#34;选择项目&#34;文字作为第一项。所以我们必须在itemStringArrayList
。
itemStringArrayList.add("Select Item");
现在我们有一个数组列表itemsArrayList
,我们想在下拉列表中显示两个元素。但这里的条件是......如果我们不选择任何内容,那么Select Item
应该显示为第一个不会启用的元素。
所以我们可以像这样实现这个功能。如果需要将数组列表项加载到android微调器中。所以你必须使用一些适配器。所以我在这里使用ArrayAdapter
。我们也可以使用自定义适配器。
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);
此代码中的代码。我们正在使用自定义的微调器布局,即R.layout.spinner_item
。它是一个简单的文本视图
<?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方法来设置颜色。因此,通过这种方式,我们将获得预期的微调器。
答案 20 :(得分:1)
此外,有一个简单的技巧可以显示默认值:
您可以在列表中添加默认值,然后使用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);
希望它可以恢复您的复杂性。编码愉快!
答案 21 :(得分:1)
扩展SpinnerAdapter
时,您会覆盖两个View
- 生成方法,getView(int, View, ViewGroup)
和getDropDownView(int, View, ViewGroup)
。第一个提供插入View
本身的Spinner
;第二个提供下拉列表中的View
(顾名思义)。您可以覆盖getView(...)
,以便在选择某个项目之前,它会显示包含提示的TextView
;然后,当您检测到某个项目已被选中时,您将其更改为显示与其对应的TextView
。
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;
}
}
//...
}
答案 22 :(得分:1)
对于那些使用Xamarin的人来说,这里的C#相当于aaronvargas的答案。
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;
}
}
}
答案 23 :(得分:0)
昨天我遇到了同样的问题,并且不想在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;
}
}
}
在初始化Spinner时,Android会在为T[] objects
中的所有项目调用getView之前调用所选项目的getView。
第一次调用SpinnerAdapterWithInitialText
时,TextView
会返回initialText
super.getView
。
所有其他时间它调用getView
ArrayAdapter
initialText
方法,如果您正常使用微调器,则会调用selectionMade
方法。
要确定用户是否选择了微调器项目,或者微调器是否仍显示private class MyClass {
private String first;
private String second;
MyClass(String first, String second) {
this.first = first;
this.second = second;
}
@Override
public String toString() {
return "MyClass [first=" + first + ", second=" + second + "]";
}
}
List<MyClass> list = Files.lines(path)
.map(line -> line.split(";"))
.map(splittedLine -> new MyClass(splittedLine[0], splittedLine[1]))
.collect(Collectors.toList());
System.out.println(list);
,请调用Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(this, R.string.no_apps_to_handle_intent, Toast.LENGTH_SHORT).show();
}
并移交适配器所指定的微调器。
答案 24 :(得分:0)
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();
}
};
答案 25 :(得分:0)
为此找到的最佳解决方案实际上是不使用Spinner,而是使用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上设置适配器。
答案 26 :(得分:0)
让它变得如此简单:
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) {
}
});
答案 27 :(得分:0)
请参阅上述答案之一:https://stackoverflow.com/a/23005376/1312796
我添加了我的代码来修复一个小bug。没有数据检索的地方..如何显示提示文字..!
这是我的伎俩...它对我很好。 !
尝试将您的微调器放在Relative_layout中,并将Textview与您的微调器对齐,并在旋转器的适配器加载或清空时播放Textview(SHOW / HIDE)的可见性。就像这样:
<?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"
/>
以下是代码:
txt__from = (TextView) rootView.findViewById(R.id.txt_prompt_from);
在微调器适配器加载和清空之前和之后调用此方法。
setPromptTextViewVisibility (); //True or fales
public void setPromptTextViewVisibility (boolean visible )
{
if (visible)
{
txt_from.setVisibility(View.VISIBLE);
}
else
{
txt_from.setVisibility(View.INVISIBLE);
}
}
答案 28 :(得分:0)
这是一个简单的
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);
}
答案 29 :(得分:0)
首先,我获取微调器的名称并使用自定义视图创建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);
}
答案 30 :(得分:0)
如果您遇到此问题当您的项目从数据库光标填充时,
我在this中找到的最简单的解决方案回答:
在游标适配器查询中使用UNION 并将具有id = -1的附加项添加到查询结果中,而不是将其真正添加到数据库中:
类似的东西:
db.rawQuery(&#34; SELECT iWorkerId as _id,nvLastName as name FROM Worker w UNION SELECT -1为_id,&#39;&#39;作为名称&#34;,null);
如果选择的项目是-1,那么它是默认值。除此以外 它是表中的记录。
答案 31 :(得分:0)
似乎是一个平庸的解决方案,但我通常只是在微调器的前面放置一个TextView。整个Xml看起来像这样。 (嘿伙计们,不要开枪打死我,我知道有些人不喜欢这种婚姻):
<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可能有点棘手,但可以这样做:
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) {
}
});
答案 32 :(得分:0)
我通过使用按钮代替Spinner来处理这个问题。 I have the sample project up on GitHub.
在项目中,我正在显示Spinner和按钮,以显示它们看起来确实相同。除了按钮,您可以将初始文本设置为您想要的任何内容。
这是活动的样子:
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,那么您很高兴。
答案 33 :(得分:0)
之前提交的答案都没有按照我想要的方式解决这个问题。对我来说,理想的解决方案是在首次显示微调器时提供“选择一个”(或任何初始文本)。当用户点击微调器时,初始文本不应该是显示的下拉列表的一部分。
为了使我的特定情况更加复杂,我的微调器数据来自通过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);
}
}
}
答案 34 :(得分:0)
如果您只有三个选项,我只会使用带有单选按钮的RadioGroup,您可以先将它们全部取消选中。
答案 35 :(得分:-1)
考虑有N个项目要选择。
添加这N个项目后,将提示文本添加为第(N + 1)项。
将所选项目设置为第N个位置[(第N + 1)项]。
在OnItemSelected侦听器中,如果所选位置不是N,则弹出最后一项并调用Adapter.notifyDataSetChanged()并将所选项目设置为所选位置。
这样的事情:
(A -> B) /\ A -> B
答案 36 :(得分:-2)
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中的第1项。您还可以在最后添加数据之前对项目进行排序。