2016-07-15 4 views
19

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

+0

попробуйте добавить @Override public boolean dispatchTouchEvent (MotionEvent ev) { super.dispatchTouchEvent (ev); return productGestureDetector.onTouchEvent (ev); } к вашей деятельности –

+0

@Stella Вы пробовали dispatchTouchEvent в своей деятельности? – Nisarg

+0

Попробуйте найти метод touchTellIntercept для управления жестами в любом виде макета. –

ответ

10

Что летнее u пытаться сделать это в основном поведение по умолчанию в Android Wear и его рассматривать как стандартные практики в Android Watches, чтобы существовать и приложение. В одежде DismissOverlayView для Android.

Смартфоны имеют заднюю кнопку, в то время как Wear полагаются на длительное нажатие или прокрутку, чтобы выйти из экрана. Вы должны уволить деятельность на заднем прессе, смешивая модель износа в Android Смартфоны заставят пользователя запутаться. По крайней мере, покажите предупреждение, чтобы избежать случайного выхода.

Решение

Как я вижу этот вопрос с тегами Android Activity Я хотел бы предложить вам сделать Base активности, которая будет заботиться о красть жест и 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 подход
  • Чистый не code- нет необходимости писать салфетки слушателя в каждом типе компоновки, используемой в проекте (относительный, линейный и т.д.)
  • Совершенно работайте в ScrollView
+1

Работает отлично с броском. Любая идея, как тянуть деятельность вместе с пальцем и увольнять? –

+0

@ hitesh-sahu вы можете ответить на вопрос, заданный Сэшу, мне тоже это нужно. –

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

Это не работает, если я установил событие click для любого из дочерних элементов. – Stella

+0

вы должны проверить детскую область внутри вас, проведите пальцем ..... проверьте площадь, соответствующую родительскому месту, и сравните высоту, чем проверьте его. –

1

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

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

Я считаю, что проблема, с которой вы работаете в RecyclerView и ScrollView, связана с дочерними элементами, получающими фокус перед родителями. вы можете попытаться установить android:descendantFocusability="beforeDescendants" для просмотра Recycler/Scroll.

0

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

Получить его из 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(); 
        } 
       }); 
    } 

После этого передать ваш макет идентификатор метода, помещенного в базовой деятельности

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

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

Смежные вопросы