Уволить закусочную по левому свайпу


Простой код ниже для показа закусочной.

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

Этот код правильно показывает закусочную, когда происходит событие onClick.

Кроме того, эта закусочная может быть отклонена жестом салфетки.

Но по умолчанию толькоправый свайп отключает закусочную. И я не могу отмахнуться от него с помощью левого свайпа.

Как отключить snackbar на левый свайп ?

3 12

3 ответа:

Это отклонит 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();
            }
        }

Надеюсь, это поможет :

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

Как использовать: On 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() {

            }
        });

    }
}

В комментариях кто-то предложил использовать CoordinatorLayout.Behavior, это правильный подход. Обработка события касания самостоятельно, это почти хорошая идея, но нет правильного подхода, потому что это "сломает" внутреннюю реализацию Snackbar и его менеджера.

Вам нужно заменить default SwipeToDismissBehavior из Snackbar сразу после вызова метода show ().

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