向右滑动结束 activity?
End up activity on swipe right?
当用户在屏幕的任意位置向右滑动时,我必须完成 Activity
。我已经尝试使用 GestureDetector
,如果 Activity
中既不存在 ScrollView
也不存在 RescyclerView
并且此外具有 onClickListener
的视图也没有' 允许检测在它们上面滑动。因此,我尝试了一种不同的方法,即以编程方式将视图叠加到所有视图顶部的布局中,然后尝试检测其上的滑动事件。
private void swipeOverToExit(ViewGroup rootView) {
OverlayLayout child = new OverlayLayout(this);
ViewGroup.LayoutParams layoutParams =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
child.setLayoutParams(layoutParams);
rootView.addView(child);
}
OverlayLayout
public class OverlayLayout extends RelativeLayout {
private float x1, x2;
private final int MIN_DISTANCE = 150;
public OverlayLayout(Context context) {
super(context);
}
public OverlayLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
* logic there.
*/
final int action = MotionEventCompat.getActionMasked(event);
Logger.logD("Intercept===", action + "");
// Always handle the case of the touch gesture being complete.
if (action == MotionEvent.ACTION_DOWN) {
return true; // Intercept touch event, let the parent handle swipe
}
Logger.logD("===", "Out side" + action + "");
// In general, we don't want to intercept touch events. They should be
// handled by the child view.
return false;
}
@Override
public boolean onTouchEvent(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) {
Logger.logD("Swipe Right===", MIN_DISTANCE + "");
return true;
} else {
Logger.logD("Tap===", "Tap===");
return super.onTouchEvent(event);
}
}
return true;
}
}
如果在 OverlayLayout
上执行滑动操作,则逻辑是拦截其他视图的触摸事件,然后进一步结束 Activity
。但是,现在我可以在 OverlayLayout
上检测到滑动事件,但其他视图无法响应,即使我在 onTouchEvent
的其他条件下有 return return super.onTouchEvent(event);
,正如你可以弄清楚的那样在我的代码中。任何人都请帮助我做到这一点。我被固定在这里并且非常兴奋地学习技巧:)
试试这个我正在使用功能进行滑动
查看滑动...
yourview.setOnTouchListener(new SimpleGestureFilter(this)); // yourview is layout or container to swipe
SimpleGestureFilter class
public class SimpleGestureFilter implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
private Context activity;
static final int MIN_DISTANCE = 100;// TODO change this runtime based on screen resolution. for 1920x1080 is to small the 100 distance
private float downX, downY, upX, upY;
// private NDAAgreementActivity mMainActivity;
public SimpleGestureFilter(Context mainActivity) {
activity = mainActivity;
}
public void onRightToLeftSwipe() {
//do your code to right to left
}
public void onLeftToRightSwipe() {
//do your code to left to right
}
public void onTopToBottomSwipe() {
}
public void onBottomToTopSwipe() {
}
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// swipe horizontal?
if (Math.abs(deltaX) > MIN_DISTANCE) {
// left or right
if (deltaX < 0) {
this.onLeftToRightSwipe();
return true;
}
if (deltaX > 0) {
this.onRightToLeftSwipe();
return true;
}
} else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long horizontally, need at least " + MIN_DISTANCE);
// return false; // We don't consume the event
}
// swipe vertical?
if (Math.abs(deltaY) > MIN_DISTANCE) {
// top or down
if (deltaY < 0) {
this.onTopToBottomSwipe();
return true;
}
if (deltaY > 0) {
this.onBottomToTopSwipe();
return true;
}
} else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long vertically, need at least " + MIN_DISTANCE);
// return false; // We don't consume the event
}
return false; // no swipe horizontally and no swipe vertically
}// case MotionEvent.ACTION_UP:
}
return false;
}
}
您尝试做的基本上是 Android Wear 中的默认行为,它被视为 Android Watches
中退出应用程序的标准做法。
在 Android wear DismissOverlayView 中为您完成所有繁重的工作。
智能手机有后退按钮,而 Wear 依靠长按或滑动关闭模式退出屏幕。您应该在后按时关闭 Activity,在 Android 智能手机中混合磨损模式会使用户感到困惑。至少显示一个警告对话框以避免意外退出。
解决方案
我看到这个问题被标记为 Android Activity
我建议你做一个 Base Activity 来处理滑动手势和 finish()
本身从左向右滑动。
基础 activity class 应该是这样的:-
public abstract class SwipeDismissBaseActivity extends AppCompatActivity {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gestureDetector = new GestureDetector(new SwipeDetector());
}
private class SwipeDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// Check movement along the Y-axis. If it exceeds SWIPE_MAX_OFF_PATH,
// then dismiss the swipe.
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// Swipe from left to right.
// The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE)
// and a certain velocity (SWIPE_THRESHOLD_VELOCITY).
if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
finish();
return true;
}
return false;
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TouchEvent dispatcher.
if (gestureDetector != null) {
if (gestureDetector.onTouchEvent(ev))
// If the gestureDetector handles the event, a swipe has been
// executed and no more needs to be done.
return true;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
}
Now you can make other activities extend this base Activity and they
will Inheritance
will automatically make them adopt swipe to dismiss
behavior .
public class SomeActivity extends SwipeDismissBaseActivity {
这种方式的优点
- 纯粹的 OOPS 方法
- 简洁的代码 - 无需在项目中使用的每种布局类型(相对、线性等)中编写滑动侦听器
- 在 ScrollView 中完美工作
关于 Activity 覆盖,我遇到了同样的问题。这对我有用
1) 定义你的SwipeListener
public class SwipeListener implements View.OnTouchListener {
private SwipeListenerInterface activity;
private float downX, downY, upX, upY;
public SwipeListener(SwipeListenerInterface activity) {
this.activity = activity;
}
public void onRightToLeftSwipe(View v) {
Log.i(logTag, "RightToLeftSwipe!");
activity.onRightToLeftSwipe(v);
}
public void onLeftToRightSwipe(View v) {
Log.i(logTag, "LeftToRightSwipe!");
activity.onLeftToRightSwipe(v);
}
public void onTopToBottomSwipe(View v) {
Log.i(logTag, "TopToBottomSwipe!");
activity.onTopToBottomSwipe(v);
}
public void onBottomToTopSwipe(View v) {
Log.i(logTag, "BottomToTopSwipe!");
activity.onBottomToTopSwipe(v);
}
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
if (deltaX < 0 ) {
this.onLeftToRightSwipe(v);
return true;
}
if (deltaX > 0 ) {
this.onRightToLeftSwipe(v);
return true;
}
if (deltaY < 0) {
this.onTopToBottomSwipe(v);
return true;
}
if (deltaY > 0) {
this.onBottomToTopSwipe(v);
return true;
}
}
}
return false;
}
public void setSwipeRestrictions(int swipeRestrictionX, int swipeRestrictionY) {
this.swipeRestrictionX = swipeRestrictionX;
this.swipeRestrictionY = swipeRestrictionY;
}
2) 使用以下参考接口
public interface SwipeListenerInterface {
void onRightToLeftSwipe(View v);
void onLeftToRightSwipe(View v);
void onTopToBottomSwipe(View v);
void onBottomToTopSwipe(View v);
}
3) 创建对象并将其绑定到您的 overlayView(确保将界面调整为 overLay 视图,以便它可以接收回调)
sl = new SwipeListener(this);
overlayView.setOnTouchListener(sl);
我认为 RecyclerView 和 ScrollView 的问题与子元素先于父元素获得焦点有关。您可以尝试为 Recycler/Scroll 视图设置 android:descendantFocusability="beforeDescendants"
。
SwipeBack 是一个 android 库,用于 Activities
的功能与 android "back-button" 的功能完全相同,但非常直观使用滑动手势的方式。
从maven central获取
compile 'com.hannesdorfmann:swipeback:1.0.4'
创建基地activity并记下方法
public void initDrawerSwipe(int layoutId) {
SwipeBack.attach(this, Position.LEFT)
.setContentView(layoutId)
.setSwipeBackView(R.layout.layout_swipe_back)
.setSwipeBackTransformer(new SlideSwipeBackTransformer() {
@Override
public void onSwipeBackCompleted(SwipeBack swipeBack, Activity activity) {
supportFinishAfterTransition();
}
});
}
然后将您的布局 ID 传递给放置在您的基础中的方法 activity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDrawerSwipe(R.layout.activity_stylists);
}
这适用于您在查询中指出的所有情况。
当用户在屏幕的任意位置向右滑动时,我必须完成 Activity
。我已经尝试使用 GestureDetector
,如果 Activity
中既不存在 ScrollView
也不存在 RescyclerView
并且此外具有 onClickListener
的视图也没有' 允许检测在它们上面滑动。因此,我尝试了一种不同的方法,即以编程方式将视图叠加到所有视图顶部的布局中,然后尝试检测其上的滑动事件。
private void swipeOverToExit(ViewGroup rootView) {
OverlayLayout child = new OverlayLayout(this);
ViewGroup.LayoutParams layoutParams =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
child.setLayoutParams(layoutParams);
rootView.addView(child);
}
OverlayLayout
public class OverlayLayout extends RelativeLayout {
private float x1, x2;
private final int MIN_DISTANCE = 150;
public OverlayLayout(Context context) {
super(context);
}
public OverlayLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
* logic there.
*/
final int action = MotionEventCompat.getActionMasked(event);
Logger.logD("Intercept===", action + "");
// Always handle the case of the touch gesture being complete.
if (action == MotionEvent.ACTION_DOWN) {
return true; // Intercept touch event, let the parent handle swipe
}
Logger.logD("===", "Out side" + action + "");
// In general, we don't want to intercept touch events. They should be
// handled by the child view.
return false;
}
@Override
public boolean onTouchEvent(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) {
Logger.logD("Swipe Right===", MIN_DISTANCE + "");
return true;
} else {
Logger.logD("Tap===", "Tap===");
return super.onTouchEvent(event);
}
}
return true;
}
}
如果在 OverlayLayout
上执行滑动操作,则逻辑是拦截其他视图的触摸事件,然后进一步结束 Activity
。但是,现在我可以在 OverlayLayout
上检测到滑动事件,但其他视图无法响应,即使我在 onTouchEvent
的其他条件下有 return return super.onTouchEvent(event);
,正如你可以弄清楚的那样在我的代码中。任何人都请帮助我做到这一点。我被固定在这里并且非常兴奋地学习技巧:)
试试这个我正在使用功能进行滑动
查看滑动...
yourview.setOnTouchListener(new SimpleGestureFilter(this)); // yourview is layout or container to swipe
SimpleGestureFilter class
public class SimpleGestureFilter implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
private Context activity;
static final int MIN_DISTANCE = 100;// TODO change this runtime based on screen resolution. for 1920x1080 is to small the 100 distance
private float downX, downY, upX, upY;
// private NDAAgreementActivity mMainActivity;
public SimpleGestureFilter(Context mainActivity) {
activity = mainActivity;
}
public void onRightToLeftSwipe() {
//do your code to right to left
}
public void onLeftToRightSwipe() {
//do your code to left to right
}
public void onTopToBottomSwipe() {
}
public void onBottomToTopSwipe() {
}
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// swipe horizontal?
if (Math.abs(deltaX) > MIN_DISTANCE) {
// left or right
if (deltaX < 0) {
this.onLeftToRightSwipe();
return true;
}
if (deltaX > 0) {
this.onRightToLeftSwipe();
return true;
}
} else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long horizontally, need at least " + MIN_DISTANCE);
// return false; // We don't consume the event
}
// swipe vertical?
if (Math.abs(deltaY) > MIN_DISTANCE) {
// top or down
if (deltaY < 0) {
this.onTopToBottomSwipe();
return true;
}
if (deltaY > 0) {
this.onBottomToTopSwipe();
return true;
}
} else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long vertically, need at least " + MIN_DISTANCE);
// return false; // We don't consume the event
}
return false; // no swipe horizontally and no swipe vertically
}// case MotionEvent.ACTION_UP:
}
return false;
}
}
您尝试做的基本上是 Android Wear 中的默认行为,它被视为 Android Watches
中退出应用程序的标准做法。
在 Android wear DismissOverlayView 中为您完成所有繁重的工作。
智能手机有后退按钮,而 Wear 依靠长按或滑动关闭模式退出屏幕。您应该在后按时关闭 Activity,在 Android 智能手机中混合磨损模式会使用户感到困惑。至少显示一个警告对话框以避免意外退出。
解决方案
我看到这个问题被标记为 Android Activity
我建议你做一个 Base Activity 来处理滑动手势和 finish()
本身从左向右滑动。
基础 activity class 应该是这样的:-
public abstract class SwipeDismissBaseActivity extends AppCompatActivity {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gestureDetector = new GestureDetector(new SwipeDetector());
}
private class SwipeDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// Check movement along the Y-axis. If it exceeds SWIPE_MAX_OFF_PATH,
// then dismiss the swipe.
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// Swipe from left to right.
// The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE)
// and a certain velocity (SWIPE_THRESHOLD_VELOCITY).
if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
finish();
return true;
}
return false;
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TouchEvent dispatcher.
if (gestureDetector != null) {
if (gestureDetector.onTouchEvent(ev))
// If the gestureDetector handles the event, a swipe has been
// executed and no more needs to be done.
return true;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
}
Now you can make other activities extend this base Activity and they will
Inheritance
will automatically make them adopt swipe to dismiss behavior .
public class SomeActivity extends SwipeDismissBaseActivity {
这种方式的优点
- 纯粹的 OOPS 方法
- 简洁的代码 - 无需在项目中使用的每种布局类型(相对、线性等)中编写滑动侦听器
- 在 ScrollView 中完美工作
关于 Activity 覆盖,我遇到了同样的问题。这对我有用
1) 定义你的SwipeListener
public class SwipeListener implements View.OnTouchListener {
private SwipeListenerInterface activity;
private float downX, downY, upX, upY;
public SwipeListener(SwipeListenerInterface activity) {
this.activity = activity;
}
public void onRightToLeftSwipe(View v) {
Log.i(logTag, "RightToLeftSwipe!");
activity.onRightToLeftSwipe(v);
}
public void onLeftToRightSwipe(View v) {
Log.i(logTag, "LeftToRightSwipe!");
activity.onLeftToRightSwipe(v);
}
public void onTopToBottomSwipe(View v) {
Log.i(logTag, "TopToBottomSwipe!");
activity.onTopToBottomSwipe(v);
}
public void onBottomToTopSwipe(View v) {
Log.i(logTag, "BottomToTopSwipe!");
activity.onBottomToTopSwipe(v);
}
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
if (deltaX < 0 ) {
this.onLeftToRightSwipe(v);
return true;
}
if (deltaX > 0 ) {
this.onRightToLeftSwipe(v);
return true;
}
if (deltaY < 0) {
this.onTopToBottomSwipe(v);
return true;
}
if (deltaY > 0) {
this.onBottomToTopSwipe(v);
return true;
}
}
}
return false;
}
public void setSwipeRestrictions(int swipeRestrictionX, int swipeRestrictionY) {
this.swipeRestrictionX = swipeRestrictionX;
this.swipeRestrictionY = swipeRestrictionY;
}
2) 使用以下参考接口
public interface SwipeListenerInterface {
void onRightToLeftSwipe(View v);
void onLeftToRightSwipe(View v);
void onTopToBottomSwipe(View v);
void onBottomToTopSwipe(View v);
}
3) 创建对象并将其绑定到您的 overlayView(确保将界面调整为 overLay 视图,以便它可以接收回调)
sl = new SwipeListener(this);
overlayView.setOnTouchListener(sl);
我认为 RecyclerView 和 ScrollView 的问题与子元素先于父元素获得焦点有关。您可以尝试为 Recycler/Scroll 视图设置 android:descendantFocusability="beforeDescendants"
。
SwipeBack 是一个 android 库,用于 Activities
的功能与 android "back-button" 的功能完全相同,但非常直观使用滑动手势的方式。
从maven central获取
compile 'com.hannesdorfmann:swipeback:1.0.4'
创建基地activity并记下方法
public void initDrawerSwipe(int layoutId) {
SwipeBack.attach(this, Position.LEFT)
.setContentView(layoutId)
.setSwipeBackView(R.layout.layout_swipe_back)
.setSwipeBackTransformer(new SlideSwipeBackTransformer() {
@Override
public void onSwipeBackCompleted(SwipeBack swipeBack, Activity activity) {
supportFinishAfterTransition();
}
});
}
然后将您的布局 ID 传递给放置在您的基础中的方法 activity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDrawerSwipe(R.layout.activity_stylists);
}
这适用于您在查询中指出的所有情况。