web-dev-qa-db-fra.com

Comment éviter un pain grillé s'il y en a déjà un montré

J'ai plusieurs SeekBar et onSeekBarProgressStop(), je veux montrer un message Toast.

Mais si sur SeekBar j'exécute l'action rapidement, le fil d'interface utilisateur se bloque et le message Toast attend que le fil d'interface utilisateur soit libre.

Mon souci est maintenant d'éviter le nouveau message Toast si le message Toast s'affiche déjà. Ou est leur une condition par laquelle nous vérifions que le fil de l'interface utilisateur est actuellement libre alors je montrerai le message Toast.

Je l'ai essayé dans les deux sens, en utilisant runOnUIThread() et en créant un nouveau Handler.

35
Deepak Goel

J'ai essayé une variété de choses pour faire cela. Au début, j'ai essayé d'utiliser cancel(), qui n'a eu aucun effet pour moi (voir aussi cette réponse ).

Avec setDuration(n), je ne venais nulle part non plus. En enregistrant getDuration(), il s’est avéré qu’elle portait la valeur 0 (si le paramètre makeText() était Toast.LENGTH_SHORT) ou 1 (si le paramètre makeText() était Toast.LENGTH_LONG).

Enfin, j'ai essayé de vérifier si la vue du pain grillé isShown(). Bien sûr, ce n'est pas le cas si aucun pain grillé n'est affiché, mais plus encore, une erreur fatale est renvoyée dans ce cas. Il me fallait donc essayer d’attraper l’erreur. Maintenant, isShown() renvoie true si un pain grillé est affiché . Utilisation de isShown() J'ai proposé la méthode suivante:

    /**
     * <strong>public void showAToast (String st)</strong></br>
     * this little method displays a toast on the screen.</br>
     * it checks if a toast is currently visible</br>
     * if so </br>
     * ... it "sets" the new text</br>
     * else</br>
     * ... it "makes" the new text</br>
     * and "shows" either or  
     * @param st the string to be toasted
     */

    public void showAToast (String st){ //"Toast toast" is declared in the class
        try{ toast.getView().isShown();     // true if visible
            toast.setText(st);
        } catch (Exception e) {         // invisible if exception
            toast = Toast.makeText(theContext, st, toastDuration);
            }
        toast.show();  //finally display it
    }
54
Addi

Ce qui suit est une solution alternative à la réponse la plus populaire , sans try/catch.

public void showAToast (String message){
        if (mToast != null) {
            mToast.cancel();
        }
        mToast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
        mToast.show();
}
36
J Wang

Une solution propre qui fonctionne hors de la boîte. Définissez ceci sur votre activité:

private Toast toast;

/**
 * Use this to prevent multiple Toasts from spamming the UI for a long time.
 */
public void showToast(CharSequence text, int duration)
{
    if (toast == null)
        toast = Toast.makeText(this, text, duration);
    else
        toast.setText(text);
    toast.show();
}

public void showToast(int resId, int duration)
{
    showToast(getResources().getText(resId), duration);
}
2
wvdz

gardez une trace de la dernière fois que vous avez montré le pain grillé et veillez à ce qu'il ne soit plus visible s'il tombe dans un intervalle.

public class RepeatSafeToast {

    private static final int DURATION = 4000;

    private static final Map<Object, Long> lastShown = new HashMap<Object, Long>();

    private static boolean isRecent(Object obj) {
        Long last = lastShown.get(obj);
        if (last == null) {
            return false;
        }
        long now = System.currentTimeMillis();
        if (last + DURATION < now) {
            return false;
        }
        return true;
    }

    public static synchronized void show(Context context, int resId) {
        if (isRecent(resId)) {
            return;
        }
        Toast.makeText(context, resId, Toast.LENGTH_LONG).show();
        lastShown.put(resId, System.currentTimeMillis());
    }

    public static synchronized void show(Context context, String msg) {
        if (isRecent(msg)) {
            return;
        }
        Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
        lastShown.put(msg, System.currentTimeMillis());
    }
}

et alors,

RepeatSafeToast.show(this, "Hello, toast.");
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown

ce n'est pas parfait, car les longueurs de LENGTH_SHORT et LENGTH_LONG ne sont pas définies, mais cela fonctionne bien dans la pratique. il présente l'avantage par rapport à d'autres solutions que vous n'avez pas besoin de conserver l'objet Toast et que la syntaxe d'appel reste concise.

1
Jeffrey Blattman

Une solution combinée

Pour mon cas, je devais annuler le toast en cours s'il était affiché et en afficher un autre. 

C'était pour résoudre le scénario où l'utilisateur demande un service alors qu'il est toujours en cours de chargement ou qu'il n'est pas disponible. Je dois montrer un toast (je pourrais être différent si le service demandé est différent). Sinon, les toasts continueront à apparaître dans l’ordre et il faudra beaucoup de temps pour les masquer automatiquement.

Donc, fondamentalement, je sauve l’instance du toast que je crée et le code suivant explique comment l’annuler en toute sécurité.

synchronized public void cancel() {
    if(toast == null) {
        Log.d(TAG, "cancel: toast is null (occurs first time only)" );
        return;
    }
    final View view = toast.getView();
    if(view == null){
        Log.d(TAG, "cancel: view is null");
        return;
    }
    if (view.isShown()) {
        toast.cancel();
    }else{
        Log.d(TAG, "cancel: view is already dismissed");
    }
}

Et pour l'utiliser, je ne peux plus m'inquiéter d'annuler comme dans:

if (toastSingleton != null ) {
    toastSingleton.cancel();
    toastSingleton.showToast(messageText);
}else{
    Log.e(TAG, "setMessageText: toastSingleton is null");
}

Le showToast est à vous de choisir comment l'implémenter car j'avais besoin d'un look personnalisé pour mon toast.

1
hannunehg

La fonction améliorée du fil précédent, qui affichera un toast uniquement si elle n’est pas visible avec le même message texte: 

 public void showSingleToast(){
        try{
            if(!toast.getView().isShown()) {    
                toast.show();
            }
        } catch (Exception exception) {
            exception.printStackTrace();       
            Log.d(TAG,"Toast Exception is "+exception.getLocalizedMessage());
            toast = Toast.makeText(this.getActivity(),   getContext().getString(R.string.no_search_result_fou`enter code here`nd), Toast.LENGTH_SHORT);
            toast.show();
        }

    }
1
Sandeep Kharat

ajouté minuterie pour enlever le pain grillé après 2 secondes.

private Toast toast;

public void showToast(String text){
        try {
            toast.getView().isShown();
            toast.setText(text);
        }catch (Exception e){
            toast = Toast.makeText(mContext, text, Toast.LENGTH_SHORT);
        }
        if(toast.getView().isShown()){
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    toast.cancel();
                }
            }, 2000);
        }else{
            toast.show();
        }
    }

showToast("Please wait");
0

Vérifiez si le message de pain grillé est affiché à l'écran, qu'il soit affiché ou non .. Pour afficher un message de pain grillé Créez une classe séparée. Et utilisez la méthode de cette classe qui affiche le message toast après avoir vérifié la visibilité du message toast. Utilisez cet extrait de code:

public class AppToast {

private static Toast toast;

public static void showToast(Context context, String message) {
    try {
        if (!toast.getView().isShown()) {
            toast=Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toast.show();
        }
    } catch (Exception ex) {
        toast=Toast.makeText(context,message,Toast.LENGTH_SHORT);
        toast.show();
    }
}

}

J'espère que cette solution vous aidera.

Merci

0
Aman Goyal

Bon pour arrêter l’empilement, par exemple cliquez conduit grillé. Basé sur la réponse de @ Addi. 

public Toast toast = null;
//....
public void favsDisplay(MenuItem item)
{
    if(toast == null) // first time around
    {
        Context context = getApplicationContext();
        CharSequence text = "Some text...";
        int duration = Toast.LENGTH_SHORT;
        toast = Toast.makeText(context, text, duration);
    }
    try
    {
        if(toast.getView().isShown() == false) // if false not showing anymore, then show it
            toast.show();
    }
    catch (Exception e)
    {}
}
0
forward creating