web-dev-qa-db-fra.com

Appels incidents invraisemblables

J'ai 36 fileuses que j'ai initialement initialisées avec certaines valeurs. J'ai utilisé OnitemSelectedlistener avec eux. Comme d'habitude, l'utilisateur peut interagir avec ces fileuses, tirant la fonction suremposeecte.

Un problème est que l'appel est effectué lors d'une invention, mais j'ai trouvé des solutions à ce sujet et évitée que l'utilisation d'une variable globale "Compte" et de vérifier si le compte> 36 avant d'exécuter le code à l'intérieur de l'Ontemselected.

Mon problème est celui-ci: L'utilisateur a la possibilité de cliquer sur un bouton appelé "Précédent", sur lequel je dois réinitialiser certaines des valeurs de filateur.

J'ai essayé de modifier la valeur du nombre de comptes vers 0 avant de réinitialiser les fileuses, puis de la modifier à 37 après la réinitialisation, mais je suis venu comprendre que l'onitemselligue n'est appelé qu'après que toutes les autres fonctions se produisent, il est donc appelé après le compte. est remplacé à 37, même si les valeurs de filateur sont définies dès qu'elles sont sélectionnées par l'utilisateur.

J'ai besoin de rafraîchir à plusieurs reprises des fileuses sans tirer la fonction surempose. Quelqu'un peut-il vous aider à trouver une solution? Merci.

19
Vedavyas Bhat

J'ai trouvé une solution simple et, je pense, une solution élégante. En utilisant des balises. J'ai d'abord créé un nouveau fichier XML appelé 'tags' et mettre dans le code suivant:

<resources xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item name="pos" type="id" />
</resources>

Chaque fois que j'utilise moi-même spin.setSelection(pos), je fais aussi spin.setTag(R.id.pos, pos), donc je définit la position actuelle en tant que balise.

Ensuite, en Onitemselected, je n'exécutant que le code if(spin.getTag(R.id.pos) != position) _, où la position est la variable de position fournie par la fonction. De cette manière, mon code est exécuté uniquement lorsque l'utilisateur effectue une sélection. Étant donné que l'utilisateur a effectué une sélection, la balise n'a pas été mise à jour. Ainsi, une fois le traitement terminé, je mettez à jour la balise comme spin.setTag(R.id.pos, position).

Remarque: il est important d'utiliser le même adaptateur tout au long, ou la variable "Position" pourrait indiquer différents éléments.

EDIT : Lorsque Kaciula a signalé, si vous n'utilisez pas plusieurs balises, vous pouvez utiliser la version plus simple, c'est-à-dire spin.setTag(pos) et spin.getTag() Sans besoin pour un fichier XML.

67
Vedavyas Bhat

Quand Spinner.Setselection (position) est utilisé, il active toujours SetonitemSelecteLecTenerner ()

Pour éviter de tirer le code deux fois, j'utilise cette solution:

     private Boolean mIsSpinnerFirstCall = true;

    ...
    Spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            //If a new value is selected (avoid activating on setSelection())
            if(!mIsSpinnerFirstCall) {
                // Your code goes gere
            }
            mIsSpinnerFirstCall = false;
        }

        public void onNothingSelected(AdapterView<?> arg0) {
        }
    });
16
Ivo Stoyanov

Je ne sais pas si cette solution est aussi infaillible que celle choisie ici, mais cela fonctionne bien pour moi et semble encore plus simple:

boolean executeOnItemSelected = false;
spinner.setSelection(pos)

Et puis dans l'onitemselectedlistener

public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    if(executeOnItemSelected){
        //Perform desired action
    } else {
        executeOnItemSelected = true;
    }
}
3
user8118328

La façon dont j'ai résolu cela consiste à sauver l'OnitemSelectedlistener d'abord. Ensuite, définissez l'ONITEMSELISÉLISTENNER DE LA SPOINTEUR À LA VALEUR NULL. Après avoir défini l'article dans la fileuse par code, restaurez à nouveau l'OnitemSelectedlistener. Cela a fonctionné pour moi.

Voir le code ci-dessous:

        // disable the onItemClickListener before changing the selection by code. Set it back again afterwards
        AdapterView.OnItemSelectedListener onItemSelectedListener = historyPeriodSpinner.getOnItemSelectedListener();
        historyPeriodSpinner.setOnItemSelectedListener(null);
        historyPeriodSpinner.setSelection(0);
        historyPeriodSpinner.setOnItemSelectedListener(onItemSelectedListener);
2
M. Oosterlee

Voici ma solution à ce problème. J'exprime AppCompatSpinner et ajoutez une méthode pgmSetSelection(int pos) qui permet le paramètre de sélection programmatique sans déclencher un rappel de sélection. J'ai codé cela avec Rxjava afin que les événements de sélection soient livrés via un Observable.

package com.controlj.view;

import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.View;
import Android.widget.AdapterView;

import io.reactivex.Observable;

/**
 * Created by clyde on 22/11/17.
 */

public class FilteredSpinner extends Android.support.v7.widget.AppCompatSpinner {
    private int lastSelection = INVALID_POSITION;


    public void pgmSetSelection(int i) {
        lastSelection = i;
        setSelection(i);
    }

    /**
     * Observe item selections within this spinner. Events will not be delivered if they were triggered
     * by a call to setSelection(). Selection of nothing will return an event equal to INVALID_POSITION
     *
     * @return an Observable delivering selection events
     */
    public Observable<Integer> observeSelections() {
        return Observable.create(emitter -> {
            setOnItemSelectedListener(new OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    if(i != lastSelection) {
                        lastSelection = i;
                        emitter.onNext(i);
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> adapterView) {
                    onItemSelected(adapterView, null, INVALID_POSITION, 0);
                }
            });
        });
    }

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

    public FilteredSpinner(Context context, int mode) {
        super(context, mode);
    }

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

    public FilteredSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public FilteredSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
        super(context, attrs, defStyleAttr, mode);
    }
}

Un exemple de son utilisation, appelé in onCreateView() dans un Fragment par exemple:

    mySpinner = view.findViewById(R.id.history);
    mySpinner.observeSelections()
        .subscribe(this::setSelection);

setSelection() est une méthode dans la vue enfermante qui ressemble à ceci, ce qui est appelé à partir des deux événements de sélection des utilisateurs via le Observable et également ailleurs de manière programmatique, de sorte que la logique des sélections de traitement est commune. aux deux méthodes de sélection.

private void setSelection(int position) {
    if(adapter.isEmpty())
        position = INVALID_POSITION;
    else if(position >= adapter.getCount())
        position = adapter.getCount() - 1;
    MyData result = null;
    mySpinner.pgmSetSelection(position);
    if(position != INVALID_POSITION) {
        result = adapter.getItem(position);
    }
    display(result);  // show the selected item somewhere
}
1
Clyde