Cómo deshabilitar el comportamiento de "snack-to-dismiss"

¿Hay alguna manera de evitar que el usuario desestime una barra de merienda pasándola?

Tengo una aplicación que muestra una barra de aperitivos durante el inicio de sesión de red, quiero evitar que sea despedido.

Según Nikola Despotoski sugerencia he experimentado ambas soluciones:

private void startSnack(){ loadingSnack = Snackbar.make(findViewById(R.id.email_login_form), getString(R.string.logging_in), Snackbar.LENGTH_INDEFINITE) .setAction("CANCEL", new OnClickListener() { @Override public void onClick(View view) { getOps().cancelLogin(); enableControls(); } }); loadingSnack.getView().setOnTouchListener(new View.OnTouchListener() { public long mInitialTime; @Override public boolean onTouch(View v, MotionEvent event) { if (v instanceof Button) return false; //Action view was touched, proceed normally. else { switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: { Log.i(TAG, "ACTION_DOWN"); mInitialTime = System.currentTimeMillis(); break; } case MotionEvent.ACTION_UP: { Log.i(TAG, "ACTION_UP"); long clickDuration = System.currentTimeMillis() - mInitialTime; if (clickDuration <= ViewConfiguration.getTapTimeout()) { return false;// click event, proceed normally } } case MotionEvent.ACTION_MOVE: { Log.i(TAG, "ACTION_MOVE"); return true; } } return true; } } }); ViewGroup.LayoutParams lp = loadingSnack.getView().getLayoutParams(); if (lp != null && lp instanceof CoordinatorLayout.LayoutParams) { ((CoordinatorLayout.LayoutParams)lp).setBehavior(new DummyBehavior()); loadingSnack.getView().setLayoutParams(lp); Log.i(TAG, "Dummy behavior assigned to " + lp.toString()); } loadingSnack.show(); } 

Esta es la clase DummyBehavior:

 public class DummyBehavior extends CoordinatorLayout.Behavior<View>{ /** * Debugging tag used by the Android logger. */ protected final static String TAG = DummyBehavior.class.getSimpleName(); public DummyBehavior() { Log.i(TAG, "Dummy behavior created"); StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); Log.i(TAG, "Method " + stackTrace[2].getMethodName() ); } public DummyBehavior(Context context, AttributeSet attrs) { super(context, attrs); Log.i(TAG, "Dummy behavior created"); } @Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean onTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean blocksInteractionBelow(CoordinatorLayout parent, View child) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); } @Override public boolean isDirty(CoordinatorLayout parent, View child) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); } @Override public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); } @Override public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return false; } @Override public WindowInsetsCompat onApplyWindowInsets(CoordinatorLayout coordinatorLayout, View child, WindowInsetsCompat insets) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return null; } @Override public void onRestoreInstanceState(CoordinatorLayout parent, View child, Parcelable state) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); } @Override public Parcelable onSaveInstanceState(CoordinatorLayout parent, View child) { Log.i(TAG, "Method " + Thread.currentThread().getStackTrace()[2].getMethodName() ); return null; } } 

Pero mi snackbar todavía desaparece cuando swiped y este es un registro típico:

 12-02 22:26:43.864 19598-19598/ I/DummyBehavior: Dummy behavior created 12-02 22:26:43.866 19598-19598/ I/DummyBehavior: Method <init> 12-02 22:26:43.866 19598-19598/ I/LifecycleLoggingActivity: Dummy behavior assigned to android.support.design.widget.CoordinatorLayout$LayoutParams@808c0e9 12-02 22:26:44.755 19598-19598/ I/LifecycleLoggingActivity: ACTION_DOWN 12-02 22:26:44.798 19598-19598/ I/LifecycleLoggingActivity: ACTION_MOVE 12-02 22:26:44.815 19598-19598/ I/LifecycleLoggingActivity: ACTION_MOVE 12-02 22:26:44.832 19598-19598/ I/LifecycleLoggingActivity: ACTION_MOVE 12-02 22:26:44.849 19598-19598/ I/LifecycleLoggingActivity: ACTION_MOVE 12-02 22:26:44.866 19598-19598/ I/LifecycleLoggingActivity: ACTION_MOVE 12-02 22:26:44.883 19598-19598/ I/LifecycleLoggingActivity: ACTION_MOVE 

Esto funcionó para mí:

  Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView(); snackbar.setDuration(Snackbar.LENGTH_INDEFINITE); snackbar.show(); layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { ViewGroup.LayoutParams lp = layout.getLayoutParams(); if (lp instanceof CoordinatorLayout.LayoutParams) { ((CoordinatorLayout.LayoutParams) lp).setBehavior(new DisableSwipeBehavior()); layout.setLayoutParams(lp); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { layout.getViewTreeObserver().removeOnGlobalLayoutListener(this); } else { //noinspection deprecation layout.getViewTreeObserver().removeGlobalOnLayoutListener(this); } } }); 

Donde DisableSwipeBehavior es:

 public class DisableSwipeBehavior extends SwipeDismissBehavior<Snackbar.SnackbarLayout> { @Override public boolean canSwipeDismissView(@NonNull View view) { return false; } } 

Puede desactivar la transmisión de eventos táctiles en lugar de los clics en la vista Snackbar .

 mSnackBar.getView().setOnTouchListener(new View.OnTouchListener() { public long mInitialTime; @Override public boolean onTouch(View v, MotionEvent event) { if (v instanceof Button) return false; //Action view was touched, proceed normally. else { switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: { mInitialTime = System.currentTimeMillis(); break; } case MotionEvent.ACTION_UP: { long clickDuration = System.currentTimeMillis() - mInitialTime; if (clickDuration <= ViewConfiguration.getTapTimeout()) { return false;// click event, proceed normally } } } return true; } }); 

O simplemente podría reemplazar el comportamiento Snackbar con algún vacío CoordinatorLayout.Behavior :

 public CouchPotatoBehavior extends CoordinatorLayout.Behavior<View>{ //override all methods and don't call super methods. } 

Este es el comportamiento vacío, que no hace nada. Predeterminado SwipeToDismissBehavior utiliza ViewDragHelper para procesar eventos táctiles, sobre los que se dispara el despido.

  ViewGroup.LayoutParams lp = mSnackbar.getView().getLayoutParams(); if (lp instanceof CoordinatorLayout.LayoutParams) { ((CoordinatorLayout.LayoutParams)lp).setBehavior(new CouchPotatoBehavior()); mSnackbar.getView().setLayoutParams(lp); } 

Mejor solución aquí …. No proporcione CoordinatorLayout o cualquiera de sus hijos como vista en la barra de aperitivos.

 Snackbar.make(ROOT_LAYOUT , "No internet connection", Snackbar.LENGTH_INDEFINITE).show(); 

Donde, el ROOT_LAYOUT debe ser cualquier diseño excepto coordinatorlayout o su hijo.

Esto funcionó para mí:

 Snackbar snackbar = Snackbar.make(findViewById(container), R.string.offers_refreshed, Snackbar.LENGTH_LONG); final View snackbarView = snackbar.getView(); snackbar.show(); snackbarView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { snackbarView.getViewTreeObserver().removeOnPreDrawListener(this); ((CoordinatorLayout.LayoutParams) snackbarView.getLayoutParams()).setBehavior(null); return true; } }); 

¡Buena suerte! 🙂

  • Cómo personalizar el diseño de snackBar?
  • SnackBar aparecen animación
  • Android Snackbar NullPointerException en Fragmento
  • ¿Podemos realizar 2 acciones diferentes en Snack bar al mismo tiempo en android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.