Androidスピナーウィジェットで1つのアイテムを非表示にする方法を探しています。これにより、アイテムが選択されていないスピナーをシミュレートでき、onItemSelected()コールバックが常に呼び出されます。選択されたすべてのアイテム(非表示のアイテムが「現在の」アイテムである場合)通常、スピナーにはコールバックを生成しないアイテム、つまり現在のアイテムが常に1つあります。
Stackoverflowには、アイテムを無効にする(グレー表示する)方法のコードがありますが、アイテムが存在しないかのように完全に非表示にする方法はありません。
さまざまな実験を重ねた結果、さまざまな新旧のプラットフォームで動作するハッキングのようなソリューションを思いつきました。Androidプラットフォーム。見た目が難しいマイナーな外観上の欠点がいくつかあります。 「スピナーでそれをしないでください」以外の、より公式な解決策を聞きたいです。
これは常にスピナーの最初のアイテムを非表示にしますが、任意のアイテムまたは複数のアイテムを非表示にするようにかなり簡単に拡張できます。スピナーアイテムのリストの先頭に空の文字列を含むダミーアイテムを追加します。スピナーダイアログが開く前に、現在のスピナーの選択をアイテム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;
}
}
そして、アイテムのリストを作成するときにカスタムアダプタを使用します。
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);
(私はコードをテストしていません)それが役立つことを願っています。
リストを切り捨てることにより、リストの最後にあるアイテムを非表示にする方が簡単です。
ただし、まずスピナーに表示されるように選択してから、選択が表示された項目のいずれかに変更されたかどうかを確認する必要があります。
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
スピナードロップダウンでアイテムを非表示にするには、必要な基準に基づいて非表示にする必要があるアイテムの位置を渡す必要があります。ドロップダウンから選択されたアイテムを非表示にするユースケースでこれを達成しました
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);
ドロップダウンからいくつかのアイテムを選択すると、位置も変更する必要があります
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) {
}
});
興味を引くために、「プロンプト」をヒントとして使用するソリューションを作成しました。このコードはXamarin.Android
用に作成されていますが、Javaに完全に移植できます。0インデックスまたはカウントを追加せずに単純なArrayAdapter
のように使用します。ソース配列へのインデックス付きアイテム。何も選択されていない場合は、SpinnerGeolocation.SelectedItemId
を-1に設定します(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;
}
}
}
私の問題を解決したこの解決策を見つけました。
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;
}
});
一度アイテムがフィルターされると、スピナーに追加しても安全になるため、スピナーよりも配列リストに検証を行う方が良いと思います
これは非常に古い質問ですが、最初のアイテムも表示しない素敵な(そしておそらく)きれいな方法を見つけました。 @Romichの回答に触発されて、最初の項目をスキップする同様のロジックを追加しました。
これにより、任意の数のアイテム(デフォルトでは1)が効果的に非表示になります。コードは、レンダリングするオブジェクトのサイズを実際よりも短く報告するだけでなく、レンダリングするアイテムのインデックスも変更するため、任意の数のアイテムをスキップします。
物事を単純にするために、ランダムなアイテムのリストの非表示をサポートする現在使用しているソリューションを除外しましたが、コードのいくつかの調整で簡単に管理できます。
class ArrayAdapterCustom(context: Context, textViewResourceId: Int, vararg objects: String)
: ArrayAdapter<String>(context, textViewResourceId, objects) {
//Can skip first n items (skip 1 as default)
var hideFirstItemsCount = 1
override fun getCount(): Int {
return super.getCount() - hideFirstItemsCount
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
return super.getDropDownView(position + hideFirstItemsCount, convertView, parent)
}
}
私にとって最も効果的な別のアプローチは、新しい空のビューオブジェクトを返すことです。配列要素で遊んでいないので、これはかなりきれいなアプローチです。
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;
}