当用户在屏幕中的任意位置提供正确的滑动时,我必须完成Activity
。我尝试使用GestureDetector
,如果ScrollView
中既不存在RescyclerView
也不存在Activity
,并且onClickListener
也没有&{ #39; t允许检测滑过它们。所以我尝试了一种不同的方法,将一个视图以编程方式覆盖在所有这些视图的顶部,然后尝试检测它上面的滑动事件。
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
上检测到滑动事件,但即使我在return super.onTouchEvent(event);
的其他情况下返回onTouchEvent
,其他视图也无法响应,因为您可以在我的代码。任何人请帮助我做到。我固定在这里并且非常兴奋地学习这个技巧:)
答案 0 :(得分:17)
您尝试执行的操作基本上是 Android Wear 中的默认行为,并且将其视为Android Watches
中退出应用的标准做法。
在Android中,DismissOverlayView对你来说非常重要。
智能手机具有后退按钮,而Wear则依靠长按或滑动消除模式来退出屏幕。你应该在背压时解雇活动,Android智能手机中的混合磨损模式会让用户感到困惑。至少会显示一个警告对话框,以避免意外退出。
解决方案
我看到这个问题是用Android Activity
标记的,我建议您制作一个基本活动,它会处理滑动手势,而finish()
本身则会在左侧显示右键滑动。
基本活动类应如下所示: -
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);
}
}
现在你可以让其他活动扩展这个基础Activity和它们
Inheritance
会自动让他们采用滑动来解雇 行为。
public class SomeActivity extends SwipeDismissBaseActivity {
这种方式的优点
答案 1 :(得分:2)
试试这个我正在使用功能进行轻扫
查看以滑动
yourview.setOnTouchListener(new SimpleGestureFilter(this)); // yourview is layout or container to swipe
SimpleGestureFilter类
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;
}
}
答案 2 :(得分:1)
我遇到了与活动叠加相同的问题。这对我有用
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);
答案 3 :(得分:1)
我相信您对RecyclerView和ScrollView的问题与在父母之前获得焦点的子元素有关。您可以尝试为Recycler / Scroll视图设置android:descendantFocusability="beforeDescendants"
。
答案 4 :(得分:0)
SwipeBack是一个用于Activities
的android库,它与android“后退按钮”完全相同,但是使用滑动手势以非常直观的方式。
从maven中心获取
compile 'com.hannesdorfmann:swipeback:1.0.4'
创建基本活动并记下方法
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传递给放置在基本活动中的方法
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDrawerSwipe(R.layout.activity_stylists);
}
这适用于您在查询中指出的所有情况。