web-dev-qa-db-fra.com

Paramétrer un spinner onClickListener () dans Android

J'essaie d'obtenir un onClickListener qui se déclenche sur un spinner, mais l'erreur suivante apparaît:

Java.lang.RuntimeException est "N'appelez pas setOnClickListener pour un AdapterView. Vous voudrez probablement setOnItemClickListener à la place,"

Je suis sûr que je veux appeler onClickListener et non onItemClickListener. J'ai trouvé une question posée par quelqu'un d'autre sur Stack Overflow, Existe-t-il un moyen d'utiliser setOnClickListener avec Android Spinner?

La réponse a déclaré il y a:

Vous devrez définir le clic écouteur dans la vue sous-jacente (normalement un TextView avec l'id: Android.R.id.text1) du disque. À faire ainsi:

Créez un spinner personnalisé dans le constructeur (avec attributs) create la fileuse en fournissant le schéma Android.R.layout.simple_spinner_item Faites un findViewById (Android.R.id.text1) pour obtenir le TextView Maintenant, définissez le onClickListener à la TextView

J'ai essayé la réponse notée ici, mais cela ne semble pas fonctionner. J'obtiens un pointeur nul sur le TextView après avoir fait findViewById ().

Voici ce que je fais:

Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.layoutspinner,dataArray);

spinner.setAdapter(adapter);

TextView SpinnerText = (TextView)findViewById(R.id.spinnerText);
if (SpinnerText == null) {
    System.out.println("Not found");
}
else {
    SpinnerText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {
            //Do something
        }
    });
}

Fichier layoutspinner.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
                  Android:id="@+id/spinnerText"
                  Android:singleLine ="true"
                  Android:layout_width="fill_parent"
                  Android:layout_height="wrap_content"
                  Android:textSize="6pt"
                  Android:gravity="right"/>

Qu'est-ce que je fais mal?

Je suis nouveau sur Stack Overflow, je n’ai trouvé aucun moyen de poster une question supplémentaire sur l’autre fil (ou un commentaire, car je n’ai que très peu de représentants), alors j’ai commencé une nouvelle question.

Par recommandation, j'ai essayé ceci:

int a = spinnerMes.getCount();
int b = spinnerMes.getChildCount();
System.out.println("Count = " + a);
System.out.println("ChildCount = " + b);
for (int i = 0; i < b; i++) {
    View v = spinnerMes.getChildAt(i);
    if (v == null) {
        System.out.println("View not found");
    }
    else {
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Click code
            }
        });
    }
}

Mais LogCat ne montre pas de résultats prometteurs.

10-14 16:09:08.127: INFO/System.out(3116): Count = 7
10-14 16:09:08.127: INFO/System.out(3116): ChildCount = 0

J'ai testé cela sur les niveaux 7 et 8 de l'API avec les mêmes résultats.

32
blindstuff

Ce qui suit fonctionne comme vous le souhaitez, mais ce n’est pas idéal.

public class Tester extends Activity {

    String[] vals = { "here", "are", "some", "values" };
    Spinner spinner;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        spinner = (Spinner) findViewById(R.id.spin);
        ArrayAdapter<String> ad = new ArrayAdapter<String>(this, Android.R.layout.simple_dropdown_item_1line, vals);
        spinner.setAdapter(ad);
        Log.i("", "" + spinner.getChildCount());
        Timer t = new Timer();
        t.schedule(new TimerTask() {

            @Override
            public void run() {
                int a = spinner.getCount();
                int b = spinner.getChildCount();
                System.out.println("Count =" + a);
                System.out.println("ChildCount =" + b);
                for (int i = 0; i < b; i++) {
                    View v = spinner.getChildAt(i);
                    if (v == null) {
                        System.out.println("View not found");
                    } else {
                        v.setOnClickListener(new View.OnClickListener() {

                            @Override
                            public void onClick(View v) {
                                        Log.i("","click");
                                        }
                        });
                    }
                }
            }
        }, 500);
    }
}

Faites-moi savoir exactement comment vous avez besoin que la roulette se comporte et nous pourrons trouver une meilleure solution.

4
Dave.B

Voici une solution de travail:

Au lieu de définir OnClickListener du compteur, nous définissons OnTouchListener et OnKeyListener.

spinner.setOnTouchListener(Spinner_OnTouch);
spinner.setOnKeyListener(Spinner_OnKey);

et les auditeurs:

private View.OnTouchListener Spinner_OnTouch = new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            doWhatYouWantHere();
        }
        return true;
    }
};
private static View.OnKeyListener Spinner_OnKey = new View.OnKeyListener() {
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            doWhatYouWantHere();
            return true;
        } else {
            return false;
        }
    }
};
55
OferR

Utilisez la méthode suivante chaque fois que vous devez effectuer une action sur le clic du Spinner dans Android.

mspUserState.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            doWhatIsRequired();
        }
        return false;
    }
});

Une chose à garder à l'esprit est de toujours retourner False en utilisant la méthode ci-dessus. Si vous retournez True, les éléments du menu déroulant ne seront pas affichés en cliquant sur le bouton.

25
Gaurav Arora

Personnellement, j'utilise ça:

    final Spinner spinner = (Spinner) (view.findViewById(R.id.userList));
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {                

            userSelectedIndex = position;
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });  
12
Lumi

Tout d'abord, un compteur ne prend pas en charge les événements de clic d'élément. L'appel de cette méthode lève une exception.

Vous pouvez utiliser setOnItemSelectedListener:

Spinner s1;
s1 = (Spinner)findViewById(R.id.s1);
int selectionCurrent = s1.getSelectedItemPosition();

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            if (selectionCurrent != position){
                // Your code here
            }
            selectionCurrent= position;
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // Your code here
    }
});
5
sumit pandey

Je suggère que tous les événements pour Spinner sont divisés en deux types:

  1. Les événements utilisateur (vous vouliez dire "clic").

  2. Événements du programme.

Je suggère également que lorsque vous voulez attraper un événement utilisateur, vous voulez juste vous débarrasser des "événements de programme". Donc c'est assez simple:

private void setSelectionWithoutDispatch(Spinner spinner, int position) {
    AdapterView.OnItemSelectedListener onItemSelectedListener = spinner.getOnItemSelectedListener();
    spinner.setOnItemSelectedListener(null);
    spinner.setSelection(position, false);
    spinner.setOnItemSelectedListener(onItemSelectedListener);
}

Il y a un moment clé: vous avez besoin de setSelection (position, false). "false" dans le paramètre d'animation déclenchera l'événement immédiatement. Le comportement par défaut est d'envoyer l'événement à la file d'attente.

2
Slava

La classe Spinner implémente DialogInterface.OnClickListener, détournant ainsi efficacement le View.OnClickListener standard.

Si vous n'utilisez pas de spinner de sous-classe ou si vous n'en avez pas l'intention, choisissez une autre réponse. 

Sinon, ajoutez simplement le code suivant à votre spinner personnalisé:

@Override
/** Override triggered on 'tap' of closed Spinner */
public boolean performClick() {
    // [ Do anything you like here ]
    return super.performClick();
}

Exemple: affichez un indice pré-fourni via le Snackbar à chaque ouverture du Spinner: 

private String sbMsg=null;      // Message seen by user when Spinner is opened.
public void setSnackbarMessage(String msg) { sbMsg=msg; }
@Override
/** Override triggered on 'tap' of closed Spinner */
public boolean performClick() {
    if (sbMsg!=null && !sbMsg.isEmpty()) { /* issue Snackbar */ }
    return super.performClick();
}

 Trapping 'click' of closed Spinner

Un spinner personnalisé est un excellent point de départ pour la normalisation par programme de l'apparence de Spinner dans votre projet.

Si vous êtes intéressé, regardez ici

0
Bad Loser