2016-07-15 52 views
19

我必須完成Activity,當用戶在屏幕的任何地方提供正確的滑動。我嘗試過GestureDetector,如果ScrollViewActivity中都不存在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上的滑動事件,但其他視圖無法響應,即使我已返回return super.onTouchEvent(event);其他條件爲onTouchEvent,因爲您可以在我的代碼中找到它。任何人都請幫助我做到。我在這裏,超級興奮固定學習的伎倆:)

+0

嘗試添加 @Override public boolean dispatchTouchEvent(MotionEvent ev){ super.dispatchTouchEvent(ev); return productGestureDetector.onTouchEvent(ev); }到您的活動 –

+0

@Stella您是否在活動中嘗試過dispatchTouchEvent? – Nisarg

+0

嘗試搜索以任何佈局控制手勢的'touchIntercept'方法。 –

回答

10

什麼喲你試圖做的事情基本上是默認行爲,在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自動使它們採用滑動將其關閉 行爲。這種方式

  • 普爾雷OOPS方法

public class SomeActivity extends SwipeDismissBaseActivity { 

優勢

  • 清潔代碼 - 不需要寫刷卡聽衆在項目中使用的佈局每種類型(相對,直線等)
  • 在ScrollView中完美工作
  • +1

    工作完全罰款與罰款。任何想法如何拖動手指和解僱活動? –

    +0

    @ hitesh-sahu您可以回答Seshu問的問題,我也需要。 –

    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

    這是行不通的,如果我已設置點擊事件的任何孩子。 – 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中遇到的問題與在父母面前獲得焦點的子元素有關。您可以嘗試爲Recycler/Scroll視圖設置android:descendantFocusability="beforeDescendants"

    0

    SwipeBack是一個Android庫,用於和Activities做一樣的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); 
        } 
    

    這適用於所有sc您在查詢中指出的enario。