RecyclerView sets two listening postures

Keywords: Fragment

Set listening method 1

  • An Interface is defined in the Adapter;
  • Keep an interface object in the Adapter;
  • Set the interface object through the set and get methods of adapter;
  • Set itemView and view clickListener in the onBindViewHolder method, and call back to activity and fragment when the interface object is not null;
public class DemoRecyclerViewAdapter extends RecyclerView.Adapter {

    private ArrayList<String> data;

    /**
     * adapter The listening object of the item click event in
     */
    private OnClickListener onClickListener;

    public OnClickListener getOnClickListener() {
        return onClickListener;
    }

    public void setOnClickListener(OnClickListener onClickListener) {
        this.onClickListener = onClickListener;
    }

    /**
     * Get item layout
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = View.inflate(parent.getContext(), R.layout.demo_item_layout, null);
        return itemView;
    }

    /**
     * Binding data
     */
    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
        final View itemView = holder.itemView;
        TextView demoTextView = (TextView) itemView.findViewById(R.id.demo_text_view);
        demoTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Set click event and call back to page
                if (onClickListener != null) {
                    onClickListener.onClick(itemView, holder.getLayoutPosition());
                }
            }
        });
        demoTextView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                // Set long click event and call back to page
                if (onClickListener != null) {
                    onClickListener.onLongClick(itemView, holder.getLayoutPosition());
                    return true;
                }
                return false;
            }
        });
    }

    /**
     * Returns the length of the list
     */
    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    /**
     * Define the click event callback interface
     */
    interface OnClickListener {
        /**
         * Click event
         */
        void onClick(View itemView, int position);

        /**
         * Long click event
         */
        void onLongClick(View itemView, int position);
    }
}

Usage method

In Activity and Fragment, you can directly set listening through adapter

DemoRecyclerViewAdapter adapter = new DemoRecyclerViewAdapter();
adapter.setOnClickListener(new DemoRecyclerViewAdapter.OnClickListener() {
    @Override
    public void onClick(View itemView, int position) {
        // click...
    }

    @Override
    public void onLongClick(View itemView, int position) {
        // longClick...
    }
});

Set listening method 2

Although RecyclerView does not provide setOnClickListener() method such as ListView, it provides an out of the box itemTouch event, internal interface: OnItemTouchListener

public static interface OnItemTouchListener {
    // Whether to intercept touch events
    // true interception
    // false do not intercept
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e);
    // Touch event
    public void onTouchEvent(RecyclerView rv, MotionEvent e);
    // Is childView allowed to intercept events
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept);
}

As you can see from the method, it deals with the distribution of Touch events of the item; we just need to deal with whether the first method intercepts Touch events or not;
The official gives a default implementation class, which is generally integrated for processing. For methods that don't need to be processed, you don't need to rewrite them, which can reduce the amount of code and make them more beautiful;

public static class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    }
}
  • The official provides a gesture detection class GestureDetectorCompat, which well encapsulates the operation of various gestures and exposes limited methods for development;
  • RecyclerView provides a method to obtain ChildView according to coordinates;
  • To obtain ChildView, the ViewHolder of the child can be obtained by getChildViewHolder(child) method;
    See the following Demo for details:
public class OnRecyclerViewItemClickListener extends RecyclerView.SimpleOnItemTouchListener {

    private GestureDetectorCompat gestureDetectorCompat;
    private RecyclerView recyclerView;

    protected OnRecyclerViewItemClickListener(RecyclerView recyclerView) {
        this.recyclerView = recyclerView;
        gestureDetectorCompat = new GestureDetectorCompat(recyclerView.getContext(), new ItemTouchHelperGestureListener());
    }

    protected void onItemClick(@NonNull RecyclerView.ViewHolder viewHolder) {
    }

    protected void onItemLongClick(@NonNull RecyclerView.ViewHolder viewHolder) {
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        gestureDetectorCompat.onTouchEvent(e);
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        gestureDetectorCompat.onTouchEvent(e);
    }

    private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            if (child != null) {
                RecyclerView.ViewHolder childViewHolder = recyclerView.getChildViewHolder(child);
                // Click feedback processing
                onItemClick(childViewHolder);
            }
            // Intercept events;
            // return super.onSingleTapUp(e);
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
            View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            if (child != null) {
                RecyclerView.ViewHolder childViewHolder = recyclerView.getChildViewHolder(child);
                // Long press feedback processing
                onItemLongClick(childViewHolder);
            }
        }
    }
}

Usage method

recyclerView.addOnItemTouchListener(new OnRecyclerViewItemClickListener(recyclerView) {
    @Override
    protected void onItemClick(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
        super.onItemClick(viewHolder, position);
        }
    }

    @Override
    protected void onItemLongClick(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
        super.onItemLongClick(viewHolder, position);
    }
});

Posted by suncore on Sun, 29 Mar 2020 09:47:42 -0700