Comment cacher un article dans un Spinner Android
je cherche un moyen de cacher un élément dans un widget Android spinner. Cela vous permettra de simuler un spinner sans aucun item sélectionné, et garantit que le callback onItemSelected() est toujours appelé pour chaque item sélectionné (si l'item caché est l'item "courant"). Normalement, il y a toujours un élément dans le spinner qui ne génère pas de callback, à savoir le courant.
il y a un certain code sur stackoverflow pour désactiver (gris out) articles, mais pas comment cacher des objets complètement comme s'ils n'existaient pas.
après beaucoup d'expérimentation, j'ai trouvé une solution quelque peu pirate qui fonctionne sur diverses anciennes et nouvelles plates-formes Android. Il a quelques inconvénients cosmétiques mineurs qui sont difficiles à remarquer. J'aimerais quand même entendre parler d'une solution plus officielle, autre que "ne fais pas ça avec un tourniquet".
cela cache toujours le premier élément dans la broche, mais pourrait assez facilement être étendu pour cacher un arbitraire élément ou de plusieurs éléments. Ajoutez un article fictif contenant une chaîne vide au début de votre liste d'articles spinner. Vous pouvez paramétrer la sélection de spinner actuelle à l'item 0 avant que la boîte de dialogue spinner s'ouvre, ce qui simulera un spinner non sélectionné.
Spinner exemple de configuration avec ArrayAdapter méthode de remplacement:
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);
7 réponses
pour cacher un élément arbitraire ou plus d'un élément, je pense que vous pouvez implémenter votre propre adaptateur et définir l'index (ou la liste des tableaux) de l'index que vous voulez cacher.
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;
}
}
et utilisez votre adaptateur personnalisé lorsque vous créez la liste des articles.
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);
(Je n'ai pas testé le code) espoir qui aide.
il est plus facile de cacher un élément à la fin de la liste en tronquant la liste.
mais vous devez d'abord le sélectionner pour qu'il apparaisse dans le spinner, puis vérifier si la sélection a été modifiée à l'un des éléments affichés.
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
pour cacher n'importe quel élément dans la descente de spinner vous devez passer la position de l'élément qui doit hided basé sur des critères requis. J'ai réalisé cela dans un cas d'utilisation de cacher l'élément qui est sélectionné à partir de dropdown
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;
}}
et le réglage de l'adaptateur est quelque chose comme ceci
final CustomAdapter dataAdapter = new CustomAdapter(this,R.layout.spinner_item,dates);
dataAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(dataAdapter);
dataAdapter.setItemToHide(0);
lors de la sélection de certains éléments de la liste déroulante, la position doit également être changée
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) {
}
});
juste pour l'intérêt, j'ai fait une solution pour utiliser "Prompt" comme un indice. Ce code est fait pour Xamarin.Android
, mais il pourrait être parfaitement porté en Java en 10 minutes. Utilisez-le comme un simple ArrayAdapter
sans ajouter d'éléments indexés à 0 ou à count au tableau des sources. Il a également placé SpinnerGeolocation.SelectedItemId
à -1 lorsque rien n'est choisi ( hint
est l'article courant).
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;
}
}
}
je pense qu'il sera préférable de mettre la validation sur la liste des tableaux plutôt que sur Spinner car une fois l'élément filtré, il sera sûr d'ajouter dans Spinner
j'ai trouvé cette solution qui a résolu mon problème.
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;
}
});
une autre approche qui a fonctionné le mieux pour moi est de retourner un nouvel objet de vue vierge. C'est considérablement une approche propre car vous ne jouez pas avec les éléments de tableau.
créez votre classe d'Adaptateur Extension ArrayAdapter
dans votre méthode
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;
}