В конечном итоге деятельность по салфетки вправо?

Я должен закончить действие, когда пользователь предлагает правильное прокручивание в любом месте экрана. Я попытался с GestureDetector и это прекрасно работает, если в ScrollView нет ни 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 затем OverlayLayout действие. Однако теперь я могу обнаружить событие swipe на OverlayLayout но другие представления не могли ответить, хотя у меня возвращался return super.onTouchEvent(event); В противном случае условие onTouchEvent как вы можете найти его в моем коде. Любой, пожалуйста, помогите мне это сделать. Я приколол сюда и очень взволнован, чтобы узнать трюк 🙂

То, что вы пытаетесь сделать, – это, по сути, поведение по умолчанию в 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); } } 

Теперь вы можете сделать другие действия, расширяющие эту базовую активность, и они Inheritance автоматически, чтобы они приняли салфетки, чтобы отклонить поведение.

 public class SomeActivity extends SwipeDismissBaseActivity { 

Преимущества этого способа

  • Подход Purley OOPS
  • Чистый код – не нужно писать сабвуфер в каждом типе макета, используемого в проекте (относительный, линейный и т. Д.),
  • Работайте отлично в ScrollView

Попробуйте это, я использую функцию для прокрутки

Просмотр для прокрутки …

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

Я столкнулся с той же проблемой в отношении Наложения активности. Это сработало для меня

1) Определите, что вы SwipeListener

Открытый класс SwipeListener реализует 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, связана с тем, что дочерние элементы получают фокус перед родителями. Вы можете попытаться установить android:descendantFocusability="beforeDescendants" для просмотров Recycler / Scroll.

SwipeBack – это андроидная библиотека, предназначенная для того, чтобы действия были такими же, как и «back-button» андроида, но по-настоящему интуитивно понятным способом с помощью жестового салфетки.

Получите его от центрального центра

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

Затем передайте свой идентификатор макета методу, который помещен в вашу базовую активность

  @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initDrawerSwipe(R.layout.activity_stylists); } 

Это хорошо работает во всех сценариях, которые вы указали в своем запросе.