关闭 Snackbar 向左滑动

Dismiss Snackbar On left swipe

下面显示 Snackbar 的简单代码。

public void onClick(View view) {
       Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_INDEFINITE)
               .setAction("Action", null).show();
}

此代码在 onClick 事件发生时正确显示 Snackbar。

此外,可以通过滑动手势关闭此快餐栏。

但默认情况下,只有右滑 可以关闭 Snackbar。而且我无法通过向左滑动来关闭它。

如何在向左滑动时关闭小吃栏?

希望这会有所帮助:

OnSwipeTouchListener.java:

import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener (Context ctx){
        gestureDetector = new GestureDetector(ctx, new GestureListener());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                    }
                    result = true;
                } 
                else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            onSwipeBottom();
                        } else {
                            onSwipeTop();
                        }
                    }
                    result = true;

            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeRight() {
    }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }
}

如何使用:在 MainActivity 上

 public class MainActivity extends AppCompatActivity {
    CoordinatorLayout coordinatorLayout;

    private Snackbar snackbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        coordinatorLayout = (CoordinatorLayout)findViewById(R.id.coordinatorLayout); 

        snackbar = Snackbar
                .make(coordinatorLayout, "Replace with your own action", Snackbar.LENGTH_INDEFINITE)
                .setAction("RETRY", null);

        snackbar.setActionTextColor(Color.RED);

        View sbView = snackbar.getView();
        TextView textView = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setTextColor(Color.YELLOW);
        snackbar.show();

        textView.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this)
        {
            public void onSwipeTop() {

            }
            public void onSwipeRight() {

            }
            public void onSwipeLeft() {
                snackbar.dismiss();
            }
            public void onSwipeBottom() {

            }
        });

    }
}

这将关闭 snackBar 向左滑动(但没有向左滑动时的动画)

  • 使用 getView() 并采用 snackBar 布局
  • 使用setOnTouchListener
  • 检测运动并执行你的动作

完成了!

public class HomeActivity extends AppCompatActivity {

            private float x1,x2;
            static final int MIN_DISTANCE = 150;

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_home);

                RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rel);

                final Snackbar snackbar = Snackbar.make(relativeLayout, "Helloo", Snackbar.LENGTH_INDEFINITE);
                Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView();
                layout.setOnTouchListener(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        switch(event.getAction())
                        {
                            case MotionEvent.ACTION_DOWN:
                                    x1 = event.getX();
                                    break;
                            case MotionEvent.ACTION_UP:
                                    x2 = event.getX();
                                    float deltaX = x2 - x1;
                                if (Math.abs(deltaX) > MIN_DISTANCE)
                                    {// Left to Right swipe action
                                        if (x2 > x1)
                                        {
                                            Toast.makeText(HomeActivity.this, "Left to Right swipe ", Toast.LENGTH_SHORT).show ();
                                        }
                                        // Right to left swipe action
                                        else
                                        {
                                            Toast.makeText(HomeActivity.this, "Right to Left swipe ", Toast.LENGTH_SHORT).show ();
                                            snackbar.dismiss();
                                        }
                                    }
                                    else
                                    {
                                        Toast.makeText(HomeActivity.this, "Tap or Else", Toast.LENGTH_SHORT).show ();
                                    }
                                    break;
                            }

                        return false;
                    }
                });
                snackbar.show();
            }
        }

在评论中有人建议使用CoordinatorLayout.Behavior,这是正确的做法。自己处理触摸事件几乎是个好主意,但没有正确的方法,因为它会 "break" Snackbar 及其管理器的内部实现。

您需要在调用 show() 方法后立即替换 Snackbar 的默认值 SwipeToDismissBehavior

     Snackbar snackbar = Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_INDEFINITE)
           .setAction("Action", null).show();
    View snackBarView = snackbar.getView();
    final ViewGroup.LayoutParams lp = snackBarView.getLayoutParams();
    if (lp instanceof CoordinatorLayout.LayoutParams) {
        final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) lp;
        final SwipeDismissBehavior<Snackbar.SnackbarLayout> behavior = new SwipeDismissBehavior<Snackbar.SnackbarLayout>();
        behavior.setStartAlphaSwipeDistance(0.1f);
        behavior.setEndAlphaSwipeDistance(0.6f);
        behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_END_TO_START);
        behavior.setListener(new SwipeDismissBehavior.OnDismissListener() {
            @Override
            public void onDismiss(View view) {
                snackbar.dismiss();
            }

            @Override
            public void onDragStateChanged(int state) {
                switch (state) {
                    case SwipeDismissBehavior.STATE_DRAGGING:
                    case SwipeDismissBehavior.STATE_SETTLING:
                        snackbar.show();
                        break;
                    case SwipeDismissBehavior.STATE_IDLE:
                        break;
                }
            }
        });
        layoutParams.setBehavior(behavior);
    }

或更短的方法:

    View snackBarView = snackbar.getView();
    final ViewGroup.LayoutParams lp = snackBarView.getLayoutParams();
    if (lp instanceof CoordinatorLayout.LayoutParams) {
        final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) lp;
        CoordinatorLayout.Behavior behavior = layoutParams.getBehavior();
        if(behavior instanceof SwipeDismissBehavior){
            ((SwipeDismissBehavior) behavior).setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_END_TO_START); // or SwipeDismissBehavior.SWIPE_DIRECTION_ANY
        }
        layoutParams.setBehavior(behavior);
    }

另一种简单而简洁的方法如下:

val behavior = BaseTransientBottomBar.Behavior().apply {
    setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_ANY)
}
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_INDEFINITE)
    .setBehavior(behavior)
    .show()

有了这个,您不需要检查和转换布局参数,也不需要使用 onShown 回调。