如何禁用快餐栏的滑动到解散行为

有没有一种方法来防止用户通过滑动快餐栏来解雇?

我有一个在网络登录时显示小吃店的应用程序,我想避免它被解雇。

根据Nikola Despotoski的建议,我已经尝试了两种解决方案:

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(); } 

这是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; } } 

但是我的小吃店在刷卡时仍然消失,这是一个典型的日志:

 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 

这对我工作:

  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); } } }); 

其中DisableSwipeBehavior是:

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

这对我工作:

 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; } }); 

祝你好运! 🙂

您可以禁用流式触摸事件,而不是点击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; } }); 

或者你可以用一些空的CoordinatorLayout.Behavior替换Snackbar行为:

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

这是空洞的行为,什么都不做。 默认的SwipeToDismissBehavior使用ViewDragHelper处理触摸事件,触发事件触发解除。

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

更好的解决方案在这里….不要提供CoordinatorLayout或其任何孩子作为视图在小吃店。

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

其中, ROOT_LAYOUT应该是除协调员布局或其子级以外的任何布局。

这是一个解决方案,不要求你乱用ViewTreeObserver 。 请注意,以下解决方案是基于SDK 26编写的Kotlin。

BaseTransientBottomBar

 final void showView() { if (mView.getParent() == null) { final ViewGroup.LayoutParams lp = mView.getLayoutParams(); if (lp instanceof CoordinatorLayout.LayoutParams) { // If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior final CoordinatorLayout.LayoutParams clp = (CoordinatorLayout.LayoutParams) lp; final Behavior behavior = new Behavior(); behavior.setStartAlphaSwipeDistance(0.1f); behavior.setEndAlphaSwipeDistance(0.6f); behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END); behavior.setListener(new SwipeDismissBehavior.OnDismissListener() { @Override public void onDismiss(View view) { view.setVisibility(View.GONE); dispatchDismiss(BaseCallback.DISMISS_EVENT_SWIPE); } @Override public void onDragStateChanged(int state) { switch (state) { case SwipeDismissBehavior.STATE_DRAGGING: case SwipeDismissBehavior.STATE_SETTLING: // If the view is being dragged or settling, pause the timeout SnackbarManager.getInstance().pauseTimeout(mManagerCallback); break; case SwipeDismissBehavior.STATE_IDLE: // If the view has been released and is idle, restore the timeout SnackbarManager.getInstance() .restoreTimeoutIfPaused(mManagerCallback); break; } } }); clp.setBehavior(behavior); // Also set the inset edge so that views can dodge the bar correctly clp.insetEdge = Gravity.BOTTOM; } mTargetParent.addView(mView); } ... } 

如果您在showView方法中showView的源代码,则会在layoutParams为CoordinatorLayout.LayoutParams时添加行为。 我们可以通过将行为设置回null

在显示视图之前添加行为,我们应该在显示视图之后将其撤消。

 val snackbar = Snackbar.make(coordinatorLayout, "Hello World!", Snackbar.LENGTH_INDEFINITE) snackbar.show() snackbar.addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() { override fun onShown(transientBottomBar: Snackbar) { val layoutParams = transientBottomBar.view.layoutParams as? CoordinatorLayout.LayoutParams layoutParams?.let { it.behavior = null } } }) 
Interesting Posts