Detect click on RecyclerView outside of items

前端 未结 6 2417
醉话见心
醉话见心 2021-02-18 22:10

I have a RecyclerView with 2 items that don\'t fill the whole screen. How can I detect that the user clicked on the empty part of the RecyclerView (meaning clicked directly on t

相关标签:
6条回答
  • 2021-02-18 22:44

    You can subclass RecyclerView and override the dispatchTouchEvent() method to accomplish this. Using the findChildViewUnder() method, we can determine if a touch event occurs outside of the child Views, and use an interface to notify a listener if it is. In the following example, the OnNoChildClickListener interface provides that functionality.

    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: This is adapted for RecyclerView from my answer here concerning GridView.

    0 讨论(0)
  • 2021-02-18 22:47

    You just need to set a TouchListener on the RecyclerView like shown above :

    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 讨论(0)
  • 2021-02-18 22:52

    @Angel Kjoseski answer would look like this in Kotlin:

    yourRecyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
                    override fun onInterceptTouchEvent(recyclerView: RecyclerView, motionEvent: MotionEvent): Boolean {
                        return when {
                            motionEvent.action != MotionEvent.ACTION_UP || recyclerView.findChildViewUnder(motionEvent.x, motionEvent.y) != null -> false
                            else -> {
                                // do something here
                                true
                            }
                        }
                    }
    
                    override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
                    override fun onTouchEvent(recyclerView: RecyclerView, motionEvent: MotionEvent) {}
                })
    
    0 讨论(0)
  • 2021-02-18 23:02

    As mentioned in the comment

    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) {
      }
    });
    
    0 讨论(0)
  • 2021-02-18 23:03

    @driss-bounouar's answer is almost right although this will prevent the user from scrolling the recycler view as any down event will cause your action to happen. With a slight modification where we record the down event and then check on the up event if the coordinates have not changed much, then fire the event.

    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;
                        }
                    });
    
    0 讨论(0)
  • 2021-02-18 23:05
    shortcutDeviceRecly.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
    
                    if(event.getAction() == MotionEvent.ACTION_UP){
                        roomClickEvent(true, v);
                    }
    
                    return false;
                }
            });
    
    0 讨论(0)
提交回复
热议问题