2014-12-30 4 views
7

전체 화면을 채우지 않는 2 가지 항목이있는 RecyclerView가 있습니다. 사용자가 RecyclerView의 빈 부분을 클릭했다는 것을 어떻게 감지 할 수 있습니까? (이는 RecyclerView에서 직접 클릭 한 것이지 해당 항목 중 하나가 아닙니다)?항목 밖에서 RecyclerView 클릭 감지

답변

4

RecyclerView의 하위 클래스를 지정하고 dispatchTouchEvent() 메서드를 재정 의하여이를 수행 할 수 있습니다. findChildViewUnder() 메서드를 사용하면 자식 뷰 외부에서 터치 이벤트가 발생하는지 확인할 수 있으며, 청취자에게 알리려면 interface을 사용합니다. 다음 예에서 OnNoChildClickListenerinterface은 해당 기능을 제공합니다.

public class TouchyRecyclerView extends RecyclerView 
{ 
    // Depending on how you're creating this View, 
    // you might need to specify additional constructors. 
    public TouchyRecyclerView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    private OnNoChildClickListener listener; 
    public interface OnNoChildClickListener 
    { 
     public void onNoChildClick(); 
    } 

    public void setOnNoChildClickListener(OnNoChildClickListener listener) 
    { 
     this.listener = listener; 
    } 

    @Override 
    public boolean dispatchTouchEvent(MotionEvent event) 
    { 
     // The findChildViewUnder() method returns null if the touch event 
     // occurs outside of a child View. 
     // Change the MotionEvent action as needed. Here we use ACTION_DOWN 
     // as a simple, naive indication of a click. 
     if (event.getAction() == MotionEvent.ACTION_DOWN 
      && findChildViewUnder(event.getX(), event.getY()) == null) 
     { 
      if (listener != null) 
      { 
       listener.onNoChildClick(); 
      } 
     } 
     return super.dispatchTouchEvent(event); 
    } 
} 

NB :이 my answer hereGridView 관한로부터 RecyclerView하도록 구성된다. 주석

mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { 

    @Override 
    public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { 
    if (motionEvent.getAction() != MotionEvent.ACTION_UP) { 
     return false; 
    } 
    View child = recyclerView.findChildViewUnder(motionEvent.getX(), motionEvent.getY()); 
    if (child != null) { 
     // tapped on child 
     return false; 
    } else { 
     // Tap occured outside all child-views. 
     // do something 
     return true; 
    } 
    } 

    @Override 
    public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { 
    } 
}); 
+1

대단히 감사합니다. 나는 findChildViewUnder (..)와 함께 recyclerView.addOnItemTouchListener를 사용하여 끝냈다. – Omar

+0

@Omar Ah! 아주 좋아! 나는 아직도 RecyclerView에 익숙해 져 있는데, 나는 그 인터페이스를 아직 알지 못했다. 정보 주셔서 감사합니다! 그것에 대한 답을 만들어야합니다. 너는 나에게서 upvote를 얻을 것이다. –

7

당신은 단지에 TouchListener을 설정해야 RecyclerView 등 위 :

categoryTable.setAdapter(new CatgoriesAdapter(categories.getWrappedList())); 
    categoryTable.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_DOWN 
        && categoryTable.findChildViewUnder(event.getX(), event.getY()) == null) 
      { 
       // Touch outside items here, you do whatever you want 
       HideCategoryMenu(); 
      } 
      return false; 
     } 
    }); 
+0

MotionEvent.getAction() == ACTION_UP도 확인해야합니다. 그렇지 않으면 2 클릭 이벤트가 발생합니다. –

+0

감사합니다. @ greg-ennis. 코드를 업데이트했습니다. –

+0

이것은 허용 된 대답이어야합니다. 또한'MotionEvent.ACTION_UP' 부분 아래에'return;이 아닌'return false;가 있어야합니다. –

1

에서 언급 한 바와 같이

2

드리-bounouar의 대답은 거의 이것은을 방지 할 수있다 권리 있지만 @ 사용자가 리사이클 러 뷰를 스크롤하여 다운 이벤트로 설정하면 작업이 수행됩니다. 우리가 down 이벤트를 기록한 다음 좌표가 많이 변경되지 않은 경우 up 이벤트를 확인한 후 이벤트를 발생시키는 약간의 수정을합니다.

private MotionEvent lastRecyclerViewDownTouchEvent; 
myRecyclerView.setOnTouchListener(new View.OnTouchListener() { 
        @Override 
        public boolean onTouch(View v, MotionEvent event) { 
         if (event.getAction() == MotionEvent.ACTION_DOWN && myRecyclerView.findChildViewUnder(event.getX(), event.getY()) == null) { 
          lastRecyclerViewDownTouchEvent = event; 
         } else if (event.getAction() == MotionEvent.ACTION_UP && myRecyclerView.findChildViewUnder(event.getX(), event.getY()) == null 
           && lastRecyclerViewDownTouchEvent != null) { 
          // Check to see if it was a tap or a swipe 
          float xDelta = Math.abs(lastRecyclerViewDownTouchEvent.getX() - event.getX()); 
          float yDelta = Math.abs(lastRecyclerViewDownTouchEvent.getY() - event.getY()); 
          if (xDelta < 30 && yDelta < 30) { 
           // Do action 
          } 
          lastRecyclerViewDownTouchEvent = null; 
         } 
         return false; 
        } 
       }); 
관련 문제