我正在尝试使用默认的空选项创建一个微调器,但它显示了微调器选项中的第一个项目。如果我将空值添加到我的字符串(这是spinner中的选择源),则在打开微调器后显示空行。我该怎么办?这是我正在使用的代码:
String[] ch = {"Session1", "Session2", "Session3"};
Spinner sp = (Spinner)findViewById(R.id.spinner1);
TextView sess_name = findViewById(R.id.sessname);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,ch);
sp.setAdapter(adapter);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener({
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
int index = arg0.getSelectedItemPosition();
sess_name.setText(ch[index]);
Toast.makeText(getBaseContext(), "You have selected item : " + ch[index], Toast.LENGTH_SHORT).show();
}
答案 0 :(得分:14)
巴拉克的解决方案有问题。当您选择第一个项目时,Spinner将不会调用OnItemSelectedListener的onItemSelected()
并刷新空内容,因为前一个位置和选择位置都为0.
首先在字符串数组的开头放一个空字符串:
String[] test = {" ", "one", "two", "three"};
第二个构建适配器,不要修改getView()
,修改getDropDownView()
。将空视图的高度设置为1px。
public class MyArrayAdapter extends ArrayAdapter<String> {
private static final int ITEM_HEIGHT = ViewGroup.LayoutParams.WRAP_CONTENT;
private int textViewResourceId;
public MyArrayAdapter(Context context,
int textViewResourceId,
String[] objects) {
super(context, textViewResourceId, objects);
this.textViewResourceId = textViewResourceId;
}
@Override
public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
TextView textView;
if (convertView == null) {
textView = (TextView) LayoutInflater.from(getContext())
.inflate(textViewResourceId, parent, false);
} else {
textView = (TextView) convertView;
}
textView.setText(getItem(position));
if (position == 0) {
ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
layoutParams.height = 1;
textView.setLayoutParams(layoutParams);
} else {
ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
layoutParams.height = ITEM_HEIGHT;
textView.setLayoutParams(layoutParams);
}
return textView;
}
}
答案 1 :(得分:6)
我参加派对有点晚了,但这就是我为解决这个问题而采取的措施
如果用户取消选择初始项目,则微调器将保持初始空状态。一旦选择了初始项目,它就像'正常'一样
适用于2.3.3+,我没有在2.2及以下测试过
首先,创建一个适配器类......
public class EmptyFirstItemAdapter extends ArrayAdapter<String>{
//Track the removal of the empty item
private boolean emptyRemoved = false;
/** Adjust the constructor(s) to fit your purposes. */
public EmptyFirstitemAdapter(Context context, List<String> objects) {
super(context, android.R.layout.simple_spinner_item, objects);
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}
@Override
public int getCount() {
//Adjust the count based on the removal of the empty item
if(emptyRemoved){
return super.getCount();
}
return super.getCount()-1;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if(!emptyRemoved){
// Remove the empty item the first time the dropdown is displayed.
emptyRemoved = true;
// Set to false to prevent auto-selecting the first item after removal.
setNotifyOnChange(false);
remove(getItem(0));
// Set it back to true for future changes.
setNotifyOnChange(true);
}
return super.getDropDownView(position, convertView, parent);
}
@Override
public long getItemId(int position) {
// Adjust the id after removal to keep the id's the same as pre-removal.
if(emptyRemoved){
return position +1;
}
return position;
}
}
这是我在strings.xml中使用的字符串数组
<string-array name="my_items">
<item></item>
<item>Item 1</item>
<item>Item 2</item>
</string-array>
接下来,将OnItemSelectedListener添加到您的Spinner ...
mSpinner = (Spinner) mRootView.findViewById(R.id.spinner);
String[] opts = getResources().getStringArray(R.array.my_items);
//DO NOT set the entries in XML OR use an array directly, the adapter will get an immutable List.
List<String> vals = new ArrayList<String>(Arrays.asList(opts));
final EmptyFirstitemAdapter adapter = new EmptyFirstitemAdapter(getActivity(), vals);
mSpinner.setAdapter(adapter);
mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
//Track that we have updated after removing the empty item
private boolean mInitialized = false;
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(!mInitialized && position == 0 && id == 1){
// User selected the 1st item after the 'empty' item was initially removed,
// update the data set to compensate for the removed item.
mInitialized = true;
adapter.notifyDataSetChanged();
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Nothing to do
}
});
它可能不是一个“完美”的解决方案,但我希望它可以帮助某人。
答案 2 :(得分:2)
经过一番思考,我相信我已经找到了实现目标的方法。它涉及创建一个 自定义适配器和设置/维护一个标志,以确定是否已选择微调器中的项目。 使用此方法,您无需创建/使用false数据(空字符串)。
基本上,适配器getView
方法设置关闭的微调器的文本。所以,如果你覆盖它
并在那里设置一个条件,你可以在启动时和你做出选择后有一个空白字段
它出现在封闭的微调框中。唯一的问题是你需要记住每当你设置标志
需要在封闭的微调器中查看值。
我创建了一个小示例程序(下面的代码)。
请注意,我只添加了我的示例所需的单个构造函数。您可以实施所有标准 ArrayAdapter构造函数或仅需要的构造函数。
<强> SpinnerTest.java 强>
public class SpinnerTestActivity extends Activity {
private String[] planets = { "Mercury", "Venus", "Earth", "Mars",
"Jupiter", "Saturn", "Uranus", "Neptune" };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner spinner = (Spinner) findViewById(R.id.spinner);
CustomAdapter adapter = new CustomAdapter(this, // Use our custom adapter
android.R.layout.simple_spinner_item, planets);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
CustomAdapter.flag = true; // Set adapter flag that something
has been chosen
}
});
}
}
<强> CustomAdapter.java 强>
public class CustomAdapter extends ArrayAdapter {
private Context context;
private int textViewResourceId;
private String[] objects;
public static boolean flag = false;
public CustomAdapter(Context context, int textViewResourceId,
String[] objects) {
super(context, textViewResourceId, objects);
this.context = context;
this.textViewResourceId = textViewResourceId;
this.objects = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = View.inflate(context, textViewResourceId, null);
if (flag != false) {
TextView tv = (TextView) convertView;
tv.setText(objects[position]);
}
return convertView;
}
}
答案 3 :(得分:0)
这是我使用的。它以通用方式正确处理空(空)选择。它适用于任何模型类T,只要类T正确实现toString()
,以显示微调器中显示的文本和equals()
,以便可以通过引用而不是位置索引选择项目
package com.10xdev.android.components;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* A spinner where no selection is possible, and other enhancements.
* requires model class to properly implement Object.equals, with semantic comparaison (such as id comparaison)
* and a proper toString(), whose result will be displayed in the spinner
*
* @author tony.benbrahim
*/
public class EnhancedSpinner<T> extends Spinner {
private final EnhanceArraySpinnerAdapter<T> spinnerAdapter;
private final List<T> items = new ArrayList<>();
private T selected = null;
public EnhancedSpinner(final Context context, final AttributeSet attributeSet) {
super(context, attributeSet);
spinnerAdapter = new EnhanceArraySpinnerAdapter<>(context, items);
setAdapter(spinnerAdapter);
}
/**
* sets the items to be displayed
*
* @param items
*/
public void setItems(final List<T> items) {
this.items.clear();
//very iffy, but works because of type erasure
this.items.add((T) "");
this.items.addAll(items);
spinnerAdapter.notifyDataSetChanged();
updateSelected();
}
/**
* set the selected item. this may be called before or after setting items
*
* @param item the item to select, or null to clear the selection
*/
public void setSelected(final T item) {
this.selected = item;
updateSelected();
}
/**
* gets the selected item, or null if no item is selected
*
* @return
*/
@Override
public T getSelectedItem() {
return getSelectedItemPosition() != 0 ? (T) super.getSelectedItem() : null;
}
/**
* set the error message for the select
*
* @param errorMessage
*/
public void setError(final String errorMessage) {
final TextView errorText = (TextView) getSelectedView();
errorText.setError("error");
errorText.setTextColor(Color.RED);
errorText.setText(errorMessage);
}
private void updateSelected() {
if (selected == null) {
setSelection(0);
} else {
for (int i = 1; i < items.size(); ++i) {
if (selected.equals(items.get(i))) {
setSelection(i);
break;
}
}
}
}
private class EnhanceArraySpinnerAdapter<T> extends ArrayAdapter<T> {
private final LayoutInflater inflater;
public EnhanceArraySpinnerAdapter(final Context context, final List<T> objects) {
super(context, android.R.layout.simple_spinner_item, objects);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getDropDownView(final int position, final View convertView, final ViewGroup parent) {
final TextView textView = convertView != null ? (TextView) convertView
: (TextView) inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
final Object item = getItem(position);
textView.setText(item.toString());
final ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
layoutParams.height = position == 0 ? 1 : LayoutParams.WRAP_CONTENT;
textView.setLayoutParams(layoutParams);
return textView;
}
}
}
答案 4 :(得分:-1)
您必须将微调器的第一个元素设置为空,或者使用string
表示未选择任何内容,如下所示:
String[] ch= {"","Session1", "Session2", "Session3"};
或
String[] ch= {"Nothing selected", "Session1", "Session2", "Session3"};
希望能帮助