如何隐藏Android微调器中的一个项目

我正在寻找一种方法来隐藏Android微调控件的一个项目。 这将允许您在没有选定项目的情况下模拟微调,并确保每select一个项目(如果隐藏项目是“当前”项目),都会调用onItemSelected()callback函数。 通常情况下,微调器中总是有一个不生成callback的项目,即当前项目。

如何禁用(灰色)项目,而不是如何完全隐藏项目,如果它们不存在,那么在stackoverflow上有一些代码。

经过大量的实验,我已经想出了一个可以在各种新老Android平台上运行的黑客解决scheme。 它有一些小的化妆品缺陷,很难注意到。 我仍然想听到一个更正式的解决办法,除了“不要用一个微调”。

这总是隐藏微调器中的第一项,但可以很容易地扩展到隐藏任意项目或多个项目。 在微调项目列表的开头添加一个包含空string的虚拟项目。 您可能想要在微调对话框打开之前将当前的微调器选项设置为项目0,这将模拟未选中的微调器。

使用ArrayAdapter方法覆盖的微调器设置示例:

List<String> list = new ArrayList<String>(); list.add(""); // Initial dummy entry list.add("string1"); list.add("string2"); list.add("string3"); // Populate the spinner using a customized ArrayAdapter that hides the first (dummy) entry ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list) { @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View v = null; // If this is the initial dummy entry, make it hidden if (position == 0) { TextView tv = new TextView(getContext()); tv.setHeight(0); tv.setVisibility(View.GONE); v = tv; } else { // Pass convertView as null to prevent reuse of special case views v = super.getDropDownView(position, null, parent); } // Hide scroll bar because it appears sometimes unnecessarily, this does not prevent scrolling parent.setVerticalScrollBarEnabled(false); return v; } }; dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mySpinner.setAdapter(dataAdapter); 

要隐藏一个任意的项目或多个项目,我认为你可以实现自己的适配器,并设置要隐藏的索引的索引(或数组列表)。

 public class CustomAdapter extends ArrayAdapter<String> { private int hidingItemIndex; public CustomAdapter(Context context, int textViewResourceId, String[] objects, int hidingItemIndex) { super(context, textViewResourceId, objects); this.hidingItemIndex = hidingItemIndex; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View v = null; if (position == hidingItemIndex) { TextView tv = new TextView(getContext()); tv.setVisibility(View.GONE); v = tv; } else { v = super.getDropDownView(position, null, parent); } return v; } } 

并在创build项目列表时使用您的自定义适配器。

 List<String> list = new ArrayList<String>(); list.add(""); // Initial dummy entry list.add("string1"); list.add("string2"); list.add("string3"); int hidingItemIndex = 0; CustomAdapter dataAdapter = new CustomAdapter(this, android.R.layout.simple_spinner_item, list, hidingItemIndex); dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mySpinner.setAdapter(dataAdapter); 

(我没有testing代码)希望有所帮助。

通过截断列表来隐藏列表末尾的项目更容易。

但是,您必须先select它才能显示在微调框中,然后检查select是否已更改为显示的其中一个项目。

 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 

要隐藏微调器下拉菜单中的任何项目,您需要根据所需条件传递需要隐藏的项目的位置。 我已经在隐藏从下拉列表中select的项目的用例中实现了这一点

 public class CustomAdapter extends ArrayAdapter<String> { private List<String> dates; private int hideItemPostion; public CustomAdapter (Context context, int resource, List<String> dates) { super(context, resource,dates); this.dates=dates; } public void setItemToHide(int itemToHide) { this.hideItemPostion =itemToHide; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View v = null; if (position == hideItemPostion) { TextView tv = new TextView(getContext()); tv.setVisibility(View.GONE); tv.setHeight(0); v = tv; v.setVisibility(View.GONE); } else v = super.getDropDownView(position, null, parent); return v; }} 

并设置适配器是这样的

 final CustomAdapter dataAdapter = new CustomAdapter(this,R.layout.spinner_item,dates); dataAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item); spinner.setAdapter(dataAdapter); dataAdapter.setItemToHide(0); 

从下拉列表中select一些项目也需要更改位置

  spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> adapterView, View view, final int i, long l) { dataAdapter.notifyDataSetChanged(); mEPGDateSelector.setSelection(i); dataAdapter.setItemToHide(i);} @Override public void onNothingSelected(AdapterView<?> adapterView) { } }); 

只是为了兴趣,我提出了一个解决scheme,使用“提示”作为一个提示。 这个代码是为Xamarin.Android ,但它可以在10分钟内完全移植到Java。 像一个简单的ArrayAdapter一样使用它,而不需要向源数组添加0索引或者索引项。 它也设置SpinnerGeolocation.SelectedItemId -1当没有select( hint是当前项目)。

 public class ArrayAdapterWithHint<T>: ArrayAdapter<T> { protected bool HintIsSet = false; protected int HintResource = 0; public ArrayAdapterWithHint(Context context, int textViewResourceId, T[] objects) : base(context, textViewResourceId, objects) { } public ArrayAdapterWithHint(Context context, int hintResource, int textViewResourceId, T[] objects) : base(context, textViewResourceId, objects) { HintResource = hintResource; } public ArrayAdapterWithHint(Context context, int textViewResourceId, IList<T> objects) : base(context, textViewResourceId, objects) { } public ArrayAdapterWithHint(Context context, int hintResource, int textViewResourceId, IList<T> objects) : base(context, textViewResourceId, objects) { HintResource = hintResource; } public override View GetDropDownView(int position, View convertView, ViewGroup parent) { if (HintIsSet) return base.GetDropDownView(position + 1, convertView, parent); return base.GetDropDownView(position, convertView, parent); } public override View GetView(int position, View convertView, ViewGroup parent) { if (!HintIsSet && parent is Spinner && !string.IsNullOrWhiteSpace((parent as Spinner).Prompt)) { Insert((parent as Spinner).Prompt, 0); HintIsSet = true; (parent as Spinner).SetSelection(base.Count - 1); } if (HintIsSet && position >= base.Count - 1) { View hintView = base.GetView(0, convertView, parent); if (hintView is TextView) (hintView as TextView).SetTextAppearance( Context, HintResource); return hintView; } if (HintIsSet && position < base.Count - 1) return base.GetView(position + 1, convertView, parent); return base.GetView(position, convertView, parent); } public override long GetItemId(int position) { if (HintIsSet) { if (position >= base.Count - 1) return -1; return position; } return base.GetItemId(position); } public override int Count { get { return base.Count > 0 && HintIsSet ? base.Count - 1 : base.Count; } } } 

我认为最好在数组列表上进行validation,而不是在微调器上进行validation,因为一旦项目被过滤,就可以安全地添加到微调器

我发现这个解决scheme解决了我的问题。

 final Spinner mySpinner = (Spinner)findViewById(R.id.spinner_triptype); final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.spinner_item, R.id.weekofday, triptype_initial); final ArrayAdapter<String> adapter_temp = new ArrayAdapter<String> (this,R.layout.spinner_item, R.id.weekofday, triptype_array); mySpinner.setAdapter(adapter); mySpinner.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // display your error popup here if(flag_spinner_isFirst){ mySpinner.setAdapter(adapter_temp); flag_spinner_isFirst = false; } v.onTouchEvent(event); return true; } }); 

另一种最适合我的方法是返回一个新的空白视图对象。 这是相当干净的方法,因为你不玩数组元素。

创build扩展ArrayAdapter的适配器类

在你的方法里面

 public View getView(int position, View convertView, ViewGroup parent) { View row = getCustomView(); if(position==0) // put the desired check here. { row = new View(context); } } return row; }