Wie kann ich benachrichtigt werden, wenn sich eine Snackbar selbst entlassen hat?

79

Ich benutze eine Snackbar aus der com.android.support:design:22.2.0Bibliothek. Ich benutze es, um Löschungen rückgängig zu machen. Um mir das Leben zu erleichtern, werde ich die Benutzeroberfläche so aussehen lassen, als würden Dinge tatsächlich aus der Datenquelle gelöscht. Wenn die Schaltfläche zum Rückgängigmachen in der Snackleiste nicht gedrückt wird, führen Sie die Löschvorgänge aus der Datenquelle durch. Ich möchte also wissen, wann die Snackbar nicht mehr sichtbar ist, damit die Elemente sicher gelöscht werden können.

Ich kann getView () in der Snackbar aufrufen, bin mir aber nicht sicher, welchen Listener ich verwenden soll. Ich habe es versucht, setOnSystemUiVisibilityChangeListener()aber das hat nicht funktioniert. Ich glaube, es ist nur für die Systemstatusleiste.

Außerdem kann die Snackbar nicht erweitert werden, da sie über einen privaten Konstruktor verfügt.

Tyler Pfaff
quelle
1
Diese Funktion wird in der nächsten Version der Support-Design-Bibliothek
Tyler Pfaff,

Antworten:

177

Die Google Design Library unterstützt Snackbar-Rückrufe in Version 23. Siehe Snackbar-Dokumente und Rückrufdokumente . Sie werden dann benachrichtigt, wenn die Snackbar entlassen wird (und auch wenn sie angezeigt wird) und auch die Art der Entlassung, wenn dies für Sie nützlich ist:

snackbar.addCallback(new Snackbar.Callback() {

    @Override
    public void onDismissed(Snackbar snackbar, int event) {
      //see Snackbar.Callback docs for event details
      ...  
    }

    @Override
    public void onShown(Snackbar snackbar) {
       ...
    }
  });
and_dev
quelle
12
setCallback () ist jetzt veraltet. Verwenden Sie stattdessen addCallback ()
jds17
36
snackbar.addCallback(new Snackbar.Callback() {

    @Override
    public void onDismissed(Snackbar snackbar, int event) {
        if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
            // Snackbar closed on its own
        }
    }

    @Override
    public void onShown(Snackbar snackbar) {
        ...
    }
});
Ananth
quelle
3
Schön, das Ereignis zu erwähnen, denn der onDismissed wird auch aufgerufen, wenn auf den actionText geklickt wird
Amro elaswar
2
In den meisten Fällen ist es wahrscheinlich am besten, if (event != Snackbar.Callback.DISMISS_EVENT_ACTION)stattdessen zu überprüfen, ob Ihre Entlassungslogik nicht ausgeführt wird, wenn der Benutzer manuell entlässt oder eine Snackbar von einer anderen aufeinanderfolgenden Snackbar entlassen wird.
Shyamal
Vielen Dank für diese Zeileevent == Snackbar.Callback.DISMISS_EVENT_TIMEOUT
Pratik Butani
17

Snackbar.addCallback in Kotlin

val snackBar = Snackbar
                .make(view, "Text Snackbar", Snackbar.LENGTH_LONG)
                .addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
                    override fun onShown(transientBottomBar: Snackbar?) {
                        super.onShown(transientBottomBar)
                    }

                    override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                        super.onDismissed(transientBottomBar, event)
                    }
                })

        val snackBarView = snackBar.view
        snackBarView.setBackgroundColor(Color.RED)
        snackBar.show()
Sergey Milakov
quelle
16

Kürzlich bin ich selbst auf diese Angelegenheit gestoßen, als zum Scrollen und Zeigen von Snackback zu viele gezeigt wurden, bevor die erste überhaupt verschwand. Ich musste einen Weg finden, um zu wissen, ob die App die Snackbar hätte einrichten sollen.

Ich persönlich habe diese Lösung gefunden.

Es ist wahr, dass die Snackbar selbst keine Art von Listener für ihren Status / ihre Sichtbarkeit bietet, aber Sie können das Ansichtsobjekt trotzdem aus der Snackbar herausholen (getView ();). Über das Ansichtsobjekt haben Sie die Möglichkeit, mithilfe einer Vielzahl von Methoden Listener hinzuzufügen.

Um es zu implementieren, müssen Sie die übliche "All-in-One-Line" -Toast- / Snackbar-Verwendung verlassen, da das Hinzufügen von Listenern ungültig ist .

Ich persönlich habe OnAttachStateChangeListener gefunden, um meine Anforderungen zu erfüllen.

Lassen Sie einen Snipper mit meinem Code fallen, falls er für Sie nützlich sein könnte.

Snackbar snack = Snackbar.make(getView(), "My Placeholder Text", Snackbar.LENGTH_LONG);

snack.getView().addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
    @Override
        public void onViewAttachedToWindow(View v) {
            canDisplaySnackbar = false;
        }

    @Override
    public void onViewDetachedFromWindow(View v) {

        Handler h = new Handler();
        h.postDelayed(new Runnable() {
            @Override
            public void run() {
                canDisplaySnackbar = true;

                }
        }, 1000);
    }
});
snack.show();

Bitte beachten Sie, dass dies nur meine Implementierung für mein eigenes Problem ist. Der Handler mit einem postDelayed Runnable passt möglicherweise nicht einmal zu Ihrem Fall. Es war nur, um einen allgemeinen Überblick über die Implementierung zu geben, die ich unter Verwendung eines Snippets vorgeschlagen habe, das ich bereits besitze.

FrancescoC
quelle
4
and_devs andswer ist jetzt die bessere Antwort.
Islam A. Hassan
12

Um benachrichtigt zu werden, wenn eine Snackbar angezeigt oder geschlossen wurde, können Sie eine Snackbar.Callback über setCallback (Callback) bereitstellen.

fabelhaft
quelle
setCallBack ist jetzt veraltet, verwenden Sie stattdessen
addCallBack
5

onDismissed wird auch aufgerufen, wenn auf die Aktion Text geklickt wird, aus diesem Grund muss eine Bedingung wie gesetzt werden

event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT

Und jetzt sieht der neue Code wie folgt aus.

final Snackbar snackBar = Snackbar.make(findViewById(R.id.root_layout), result, Snackbar.LENGTH_LONG);

snackbar.addCallback(new Snackbar.Callback() {

@Override
public void onDismissed(Snackbar snackbar, int event) {
 if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
        // Snackbar closed on its own
    }  
}

@Override
public void onShown(Snackbar snackbar) {
...
}
});
snackBar.show();
Vishal G. Gohel
quelle
Code nur Antworten werden nicht empfohlen, da sie nicht viele Informationen für zukünftige Leser bieten. Bitte geben Sie eine Erklärung zu dem, was Sie geschrieben haben
WhatsThePoint
In den meisten Fällen ist es wahrscheinlich am besten, if (event != Snackbar.Callback.DISMISS_EVENT_ACTION)stattdessen zu überprüfen, ob Ihre Entlassungslogik nicht ausgeführt wird, wenn der Benutzer manuell entlässt oder eine Snackbar von einer anderen aufeinanderfolgenden Snackbar entlassen wird.
Shyamal
3

Es gibt derzeit keine Möglichkeit, eine Benachrichtigung zu erhalten, wenn die Anzeige der Snackbar beendet ist.

In diesem Thread wird eine Problemumgehung basierend auf einem Timer für die Dauer der Snackbar-Anzeige erläutert. Die Snackbar in der Support-Bibliothek enthält OnDismissListener () nicht?

Ein Problem, das bei dieser Problemumgehung berücksichtigt werden muss, ist, dass die Snackbar-Dauer möglicherweise neu gestartet wird. Die Materialdesignspezifikation für Snackbar besagt, dass dies passieren wird, wenn ein nicht verwandter Dialog oder ein Popup angezeigt wird.

BrentM
quelle
1

Derzeit können Sie es nicht erreichen.

Es wird kein Zuhörer angerufen, wenn die Snackbar verkleinert ist.

Der einfachste Weg, dies zu tun, besteht darin, den Datensatz vorübergehend an einer anderen Stelle (sogar in einer lokalen Variablen) zu speichern und ihn dann erneut einzufügen, wenn sie zufällig auf die Schaltfläche "Rückgängig" klicken.

Gabriele Mariotti
quelle
1
    snackbar.addCallback(new Snackbar.Callback() {
        public void onShown(Snackbar snackbar) {
           //  on show  
        }
 public void onDismissed(Snackbar snackbar, int event) {
          //  on dismiss  
        }
      });
Dileep krishnan
quelle
Bitte geben Sie eine Beschreibung / Erklärung neben Ihrem Code-Snippet an.
Janis F
1

Ich habe genau das gleiche Problem wie Sie. Meine Lösung ist ...

              final Snackbar povrati_obrisani_unos = Snackbar.make (coordinatorLayout, "Ponisti brisanje", Snackbar.LENGTH_INDEFINITE)
                    .addCallback (new Snackbar.Callback (){
                        @Override
                        public void onDismissed(Snackbar transientBottomBar, int event) {
                            super.onDismissed (transientBottomBar, event);
                            if(event==DISMISS_EVENT_SWIPE){//here we detect if snackbar is swipped away and not cliked (which is undo in my case)
                                Uri uriDelete = Uri.parse (obrisano.getImageuri ());
                                ContentResolver contentResolver = getContentResolver();
                                contentResolver.delete (uriDelete, null, null);
                                Toast.makeText (MainActivity.this,
                                        "Ocitavanje i slika su trajno obrisani", Toast.LENGTH_SHORT).show ();
                            }

Das ist alles, nicht Snackbar kopieren und einfügen. Aktion, die rückgängig gemacht wird. Möchte klar sein, wie ich hier nur kann.

Grüße Nenad

Nenad Štrbić
quelle
0

Dank @SergeyMilakov in Kotlin ist es:

@SuppressLint("WrongConstant") // Suppress an error when set duration.
private fun showSnackbar() {
    val DURATION = 5000

    Snackbar.make(view!!, "Remove item?"), DURATION).apply {
        setAction("Undo") {
            // Your action when a button is clicked.
        }
        addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
            /* override fun onShown(transientBottomBar: Snackbar?) {
                super.onShown(transientBottomBar)
                Timber.d("*** onShown")
            }*/

            override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                super.onDismissed(transientBottomBar, event)
                if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) {
                    // Your action when the Snackbar is closed and the button was not clicked.
                }

            }
        })
        view.setBackgroundColor(ContextCompat.getColor(context, R.color.black))
        setActionTextColor(ContextCompat.getColor(context, R.color.yellow))
        show()
    }
}

Beachten Sie, dass dies Snackbarangezeigt wird, auch wenn Sie zu anderen Bildschirmen wechseln (z. B. zurück). Vergessen Sie also nicht zu überprüfen, ob Sie auf dem rechten Bildschirm Aktionen ausführen.

Wird Snackbarauch nach der Bildschirmdrehung nicht wiederhergestellt.

CoolMind
quelle