关闭 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
回调。
下面显示 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
回调。