Item Click, Long Press Event Response and Up-Slide Loading Function Packaging of RecyclerView in android

Keywords: Android


Summary

This paper mainly introduces the Item click of RecyclerView in android, the response of long press events and the encapsulation of the sliding loading function. Previous articles introduced RecyclerView.Adapter from the perspective of RecyclerView.Adapter encapsulation and Functional Extension Then with Recycler View and Swipe RefreshLayout Up-slip Loading and Down-pull Refreshing Operation. from Up-slip Loading and Down-pull Refreshing In this article, you can see two inconveniences when using RecyclerView directly:

  1. RecyclerView does not provide Item clicks and long press events, which need to be implemented by itself.
  2. If RecyclerView is used more frequently in software, there are more scenarios that need to be loaded up. If it is not encapsulated, then every time it is loaded up, a large amount of OnScrollListener duplicate code will be written, which will affect code reading. As for drop-down refresh, it is based on Swipe Refresh Layout and does not need to be encapsulated in RecyclerView.

Item response click, long press event

There are two ways to realize the Item response click and long press events of RecyclerView:

  1. Starting from RecyclerView itself, with the help of GestureDetector class, Item clicks and long press events to respond.
  2. From the last article Encapsulation of RecyclerView.Adapter Starting from BaseAdapter, with the help of BaseAdapter, Item internal controls can be added the ability of event monitoring, and Item root office can be added an event monitoring, so as to enable Item to respond to click and press events for a long time.

Implementing Click and Long Press Event Monitoring with Gesture Detector Class

Referring to the usage of setOnClickListener() of ListView, when you want to make the Item of RecyclerView able to listen for clicks and long press events, you need to implement a listening interface and pass it in to RecyclerView. The encapsulated usage should be as follows:

//Click Events
baseRecyclerView.setOnItemClickListener(new BaseRecyclerView.OnItemClickListener() {
           @Override
           public void onItemClick(View view, BaseHolder baseHolder, int position) {
               //When you call back, you can return the view, holder and location of the Item you clicked on.
           }
       });
//Event of long press
recyclerView.setOnItemLongClickListener(new BaseRecyclerView.OnItemLongClickListener(){
           @Override
           public void onItemLongClick(View view, BaseHolder baseHolder, int position) {
               //When you call back, you can return the view, holder and location of the Item you clicked on.
           }
       });

So in the BaseRecyclerView class, you should have:

  1. Definition of OnItemClickListener interface containing onItemClick() method;
  2. The definition of OnItemClickLOngListener interface containing onItemLongClick() method;
  3. Reference variable of OnItemClickListener interface type (used to receive incoming OnItemClickListener);
  4. Reference variable of OnItemClickLongListener interface type (used to receive incoming OnItemClickLongListener);
  5. Can identify the user clicks, long clicks and callbacks of the object,
  6. setOnItemClickListener Method
  7. setOnItemLongClickListener method.

The code is shown below.

public class BaseRecyclerView extends RecyclerView {
    //Reference Variables of OnItemClickListener Interface Type
    private OnItemClickListener onItemClickListener;
    //Reference variable of OnItemClickLongListener interface type
    private OnItemLongClickListener onItemLongClickListener;
    //Can identify the user clicks, long clicks can be called back to the object
    private GestureDetectorCompat gestureDetectorCompat;
    //Constructive function of overload
    public BaseRecyclerView(Context context) {
        super(context);
        //Get an instance of Gesture Detector Compat
        this.gestureDetectorCompat = getGestureDetectorCompat();
    }

    public BaseRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.gestureDetectorCompat = getGestureDetectorCompat();
    }

    public BaseRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.gestureDetectorCompat = getGestureDetectorCompat();
    }
    //Assignment listener
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){
        this.onItemClickListener = onItemClickListener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener){
        this.onItemLongClickListener = onItemLongClickListener;
    }
    //Interface definition
    public interface OnItemClickListener{
        void onItemClick(View view, BaseHolder baseHolder, int position);
    }

    public interface OnItemLongClickListener{
        void onItemLongClick(View view, BaseHolder baseHolder, int position);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        gestureDetectorCompat.onTouchEvent(e);
        return false;
    }
    //Get an instance of Gesture Detector Compat
    public GestureDetectorCompat getGestureDetectorCompat(){

        return new GestureDetectorCompat(getContext(),
                new GestureDetector.SimpleOnGestureListener(){
                    @Override
                    public boolean onSingleTapUp(MotionEvent e) {
                      //Judge click events
                        View childView = findChildViewUnder(e.getX(), e.getY());
                        if (childView != null &&
                                onItemClickListener !=null){
                                  //Callback click event
                            onItemClickListener.onItemClick(childView,
                                    (BaseHolder)getChildViewHolder(childView),
                                    getChildAdapterPosition(childView));
                        }
                        return true;
                    }

                    @Override
                    public void onLongPress(MotionEvent e) {
                      //Judged as a long-term event
                        View childView = findChildViewUnder(e.getX(), e.getY());
                        if (childView != null && onItemLongClickListener !=null){
                          //Callback by Event
                            onItemLongClickListener.onItemLongClick(childView,
                                    (BaseHolder)getChildViewHolder(childView),
                                    getChildAdapterPosition(childView));
                        }
                    }
                });
    }
}

Implementing Click and Long Press Event Monitoring with BaseAdapter

This method is relatively simple, adding a setOnClickListener() method to the BaseAdapter to hold a reference to View.OnClickListener, and then binding the listener to Ite through the setOnClickListener(int viewId, View.OnClickListener listener) method of the BaseHolder parameter in the onBind() method of BaseAdapter. M is on the root part of Item (an id needs to be assigned to the root part of Item).

BaseAdapter improvements:

//Add a View.OnClickListener variable
 View.OnClickListener onClickListener;
//Add a setOnClickListener()
public void setOnClickListener(View.OnClickListener onClickListener){
    this.onClickListener = onClickListener;
}

Subclass Adapter needs to pay attention to passing onClickListener to holder

@Override
   public void onBind(BaseHolder holder, final Contact contact, int position) {
       holder.setOnClickListener(R.id.item, onClickListener);
   }

Usage method:

adapter.setOnClickListener(new View.OnClickListener(){
  @Override
  public void onClick(View v) {
    //Click event callback
  }
});

Encapsulate the response to the sliding load event

Improvement based on the BaseRecyclerView code above

//Define an OnLoadableListener listening interface
public interface OnLoadableListener{
    void load();
}
//Add an OnLoadableListener reference variable
private OnLoadableListener onLoadableListener;
//Adding a setter Method for Assigning OnLoadableListener
public void setOnLoadableListener(OnLoadableListener onLoadableListener){
    this.onLoadableListener = onLoadableListener;
}
//Add a function that binds the received OnLoadableListener to the current BaseRecyclerView
    public void addOnLoadableListener(OnLoadableListener onLoadableListener){
        addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //The encapsulated BaseAdapter adapter used
                if (((LinearLayoutManager)getLayoutManager()).
                        findLastVisibleItemPosition() == getAdapter().getItemCount()-1){
                    //Perform load callback operation
                    onLoadableListener.load();
                }
            }
        });
    }

Usage method

recyclerView.setOnLoadableListener(new BaseRecyclerView.OnLoadableListener() {
    @Override
    public void load() {
      if (!isLoading) {
        isLoading = true;
        //Loading operation
        //......
        isLoading = false;
      }
    }
});

Posted by rhysmeister on Thu, 04 Jul 2019 14:53:37 -0700