46 votes

Le spinner onItemSelected() s'exécute de manière inappropriée

Duplicata possible :
Android Spinner OnItemSelected Called Erroneously (without user action on opening spinner)

Quelqu'un sait-il comment empêcher la méthode onItemSelected() (interface OnItemSelectedListener) de s'exécuter lors de l'instanciation de la mise en page ? J'ai besoin de savoir s'il y a un moyen de le faire parce que je veux garder la façon dont j'instancie ma mise en page séparée de cet écouteur.

J'ai essayé de créer une instruction if initialement fixée à false autour de tout le code à l'intérieur de la méthode surchargée, mais il n'y a aucun moyen de savoir quand la fixer à true parce que la méthode surchargée s'exécute après les méthodes onCreate(), onStart(), et onResume() à chaque fois.

Je n'ai pas trouvé de réponse claire à ce sujet. Toute solution claire serait grandement appréciée.

8 votes

La façon dont le spinner est conçu me rend malade... C'est certainement le pire contrôle d'interface utilisateur avec lequel j'ai jamais travaillé...

1 votes

Doit être marqué comme un duplicata de stackoverflow.com/questions/2562248/ au lieu de cela.

0 votes

Vous pouvez trouver la réponse, j'ai répondu ici stackoverflow.com/questions/10132971/

66voto

Someone Somewhere Points 8361

David, voici un tutoriel que j'ai rédigé pour ce problème...

Énoncé du problème

un onItemSelected() indésirable est déclenché alors que la galerie (ou le Spinner) est en cours d'initialisation. Cela signifie que du code est exécuté prématurément ; du code qui est censé s'exécuter UNIQUEMENT lorsque l'utilisateur effectue physiquement une sélection.

Solution

  1. dans onCreate(), comptez le nombre de widgets Galerie (ou Spinner) que vous avez dans la vue. (mGalleryCount)
  2. dans onItemSelected(), comptez le nombre de fois où il s'est déclenché. (mGalleryInitializedCount)
  3. lorsque (mGalleryInitializedCount < mGalleryCount) == false, le code destiné à l'utilisateur est exécuté

Exemple de code

public class myActivity extends Activity implements OnItemSelectedListener
{
    //this counts how many Gallery's are on the UI
    private int mGalleryCount=0;

    //this counts how many Gallery's have been initialized
    private int mGalleryInitializedCount=0;

    //UI reference
    private Gallery mGallery;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.myxmllayout);

        //get references to UI components
        mGallery = (Gallery) findViewById(R.id.mygallery);

        //trap selection events from gallery
        mGallery.setOnItemSelectedListener(this);

        //trap only selection when no flinging is taking place
        mGallery.setCallbackDuringFling(false);

        //
        //do other stuff like load images, setAdapter(), etc
        //

        //define how many Gallery's are in this view
        //note: this could be counted dynamically if you are programmatically creating the view
        mGalleryCount=1;

    }

    public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
    {

        if (mGalleryInitializedCount < mGalleryCount)
        {
            mGalleryInitializedCount++;
        }
        else
        {
            //only detect selection events that are not done whilst initializing
            Log.i(TAG, "selected item position = " + String.valueOf(position) );
        }

    }

}

Pourquoi cela fonctionne-t-il ?

cette solution fonctionne parce que la galerie termine son initialisation bien avant que l'utilisateur ne soit physiquement en mesure de faire une sélection.

1 votes

C'est une bonne réponse, ainsi que la variante booléenne donnée par khr2003 pour une vue unique. Il semble que le chargement d'une présentation de vue et des éléments exécute l'élément sélectionné. Je pense qu'il s'agit d'un bogue puisque le mot d'action sélectionné indique une interaction de l'utilisateur et non une configuration d'initialisation.

0 votes

Merci. Cela a permis de résoudre un problème stupide :)

0 votes

Pourquoi est-ce que j'obtiens une erreur sur cette ligne : mSpinner.setCallbackDuringFling(false) ; saying : La méthode setCallbackDuringFling(boolean) est indéfinie pour le type Spinner ? Après des heures de travail, je pensais enfin avoir trouvé une solution à ce problème ennuyeux.

15voto

khr2003 Points 915

Voici une version modifiée du code de "Quelqu'un quelque part". Vous pouvez l'utiliser si vous avez une vue unique.

public class myActivity extends Activity implements OnItemSelectedListener
{
// Set view initialization to false while the it is being built
private boolean initializedView = false;

//UI reference
private Gallery mGallery;

@Override
public void onCreate(Bundle savedInstanceState)
{

    super.onCreate(savedInstanceState);
    setContentView(R.layout.myxmllayout);

    //get references to UI components
    mGallery = (Gallery) findViewById(R.id.mygallery);

    //trap selection events from gallery
    mGallery.setOnItemSelectedListener(this);

    //trap only selection when no flinging is taking place
    mGallery.setCallbackDuringFling(false);

    //
    //do other stuff like load images, setAdapter(), etc
    //

}

public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{

    if (initializedView ==  false)
    {
        initializedView = true;
    }
    else
    {
        //only detect selection events that are not done whilst initializing
        Log.i(TAG, "selected item position = " + String.valueOf(position) );
    }

}
}

0 votes

Belle solution, qui fonctionne parfaitement !

0 votes

Cette démo fonctionne parfaitement pour onItemselectedListner dans le bouton Spinner.

11voto

Dimitar Vukman Points 159

Même solution :

private int m_intSpinnerInitiCount = 0;
private static final int NO_OF_EVENTS = 1;

...

m_spnTemplates.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, 
                    View selectedItemView, int position, long id) { 

                //trying to avoid undesired spinner selection changed event, a known problem
                    if (m_intSpinnerInitiCount < NO_OF_EVENTS) {
                        m_intSpinnerInitiCount++;
                    } else {                
                        //YOUR CODE HERE
                    }                           
            }

1voto

Cliffus Points 674

J'ai également cherché une bonne solution sur l'internet, mais je n'en ai trouvé aucune qui réponde à mes besoins. J'ai donc écrit cette extension sur la classe Spinner afin que vous puissiez définir un simple OnItemClickListener, qui a le même comportement qu'une ListView.

Ce n'est que lorsqu'un élément est "sélectionné" que l'écouteur onItemClickListener est appelé.

Amusez-vous bien !

public class MySpinner extends Spinner
{
    private OnItemClickListener onItemClickListener;

    public MySpinner(Context context)
    {
        super(context);
    }

    public MySpinner(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public MySpinner(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener inOnItemClickListener)
    {
        this.onItemClickListener = inOnItemClickListener;
    }

    @Override
    public void onClick(DialogInterface dialog, int which)
    {
        super.onClick(dialog, which);

        if (this.onItemClickListener != null)
        {
            this.onItemClickListener.onItemClick(this, this.getSelectedView(), which, this.getSelectedItemId());
        }
    }
}

1voto

James Points 1560

J'ai rencontré ce problème hier avec un OnCheckedChangedListener. J'ai fini par ajouter une variable d'instance booléenne initialisée à true à l'intérieur de ma classe d'adaptateur avec une méthode d'accès isListenerEnabled(). J'ai ensuite mis la variable à false dans mon code de mise en page et je l'ai remise à true à la fin du code de mise en page. Dans mon écouteur, j'inspecte la valeur de la variable pour décider d'exécuter ou non le code de l'écouteur.

0 votes

Je vous remercie de votre réponse, mais pourriez-vous montrer un extrait de code démontrant cette solution ? Par ailleurs, ma présentation est définie dans un fichier xml et la méthode onItemSelected() s'exécute après que l'élément a été sélectionné.

0 votes

La méthode setContentView(), ce qui complique les choses.

0 votes

Postez votre code de mise en page et je pourrai vous aider. Sans cela, un extrait ne serait probablement pas très utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X