Add drop-down refresh

SwipeRefreshLayout

1. In the XML file, use SwipeRefreshLayout to layout the package

<? xml version="1.0" encoding="utf-8"? > <android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/srl_base"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_base"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>

Copy the code

2. Set the refresh callback

mSwpBase.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {// Specific refresh logic onFresh(); }});Copy the code

3. After the refresh, set the refresh status to false

mSwpBase.setRefreshing(false);
Copy the code

4. Other

// Set the background color of the progress circle. setProgressBackgroundColor(int colorRes);

// Set the color of the progress animation. SetColorSchemeResources (int… colorResIds);

// Set the size of the progress circle, with only two values: DEFAULT, LARGE) setSize(int size);

2. Add more pull-up loading (without footView)

1. Use the built-in addOnScrollListener to listen to add:

 rcBase.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); // Add(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); }});Copy the code

2. In the onAdd method to determine whether to load the last one

    public void onAdd(RecyclerView recyclerView, int newState){
        if (newState == RecyclerView.SCROLL_STATE_IDLE && mManager.findLastVisibleItemPosition() == mAdapter.getItemCount()) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SystemClock.sleep(2000);
                    list.addAll(list);
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mAdapter.notifyDataSetChanged();
                            Toast.makeText(getActivity(), "Load complete", Toast.LENGTH_SHORT).show(); }}); } }).start(); }}Copy the code

Among them:

Recyclerview. SCROLL_STATE_IDLE: Checks whether a finger leaves the screen

MManager. FindLastVisibleItemPosition () : is the last one (for LinearLayoutManager method, GridLayoutManager inheritance LinearLayoutManager)

Add more pull-up loading (footView included)

Similar to pull-up loading without footiew, but with footView, a little more judgment is needed.

RecyclerView does not have a method like listView addfootView, but there is a getItemViewType method in adapter, so we can create a different holder according to the different position

1. Override getItemViewType in Adapter:

@Override
public int getItemViewType(int position) {
   if (position + 1 == getItemCount()) {
        return TYPE_FOOTER;
    } else {
        returnTYPE_ITEM; }}Copy the code

Position +1: the number of footViews added is increased by 1

Likewise in getItemCount return list.size()+1

View private static final int TYPE_ITEM = 0;

FootView private static final int TYPE_FOOTER = 1;

2. On the basis of ViewHolder, make a FootHolder

class FootHolder extends RecyclerView.ViewHolder { private final TextView tvFt; public FootHolder(View itemView) { super(itemView); tvFt = (TextView) itemView.findViewById(R.id.tv_ft); }}Copy the code

Note: Since there are two ViewHolder classes in the inherited recyclerView. Adapter generic class need to be changed to the public parent recyclerView. ViewHolder

3. Create different views based on viewType in onCreateViewHolder and return different holders

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    if (viewType == TYPE_ITEM) {
        view = getActivity().getLayoutInflater().inflate(R.layout.fragment_video, parent, false);
        return new VideoHolder(view);
    } else if (viewType == TYPE_FOOTER) {
        view = getActivity().getLayoutInflater().inflate(R.layout.foot_view, parent, false);
        return new FootHolder(view);
    }
    return null;
}
Copy the code

4. Load the unused logic in onBindViewHoder according to the holder type

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if(holder instanceof VideoHolder) { VideoBean videoBean = list.get(position); VideoHolder videoHolder = (VideoHolder) holder; videoHolder.fbVideo.setImageURI(videoBean.getImg()); videoHolder.tvTitle.setText(videoBean.getTitle()); / / the data when the tag to the view, it is ok to write a listener videoHolder. LlVideo. SetTag (videoBean); videoHolder.llVideo.setOnClickListener(mListerner); }else if (holder instanceof FootHolder) {
        FootHolder footHolder = (FootHolder) holder;
        switch (load_more_status) {
            case PULLUP_LOAD_MORE:
                footHolder.tvFt.setText("Pull up to load more");
                break;
            case LOADING_MORE:
                footHolder.tvFt.setText("Loading more");
                break; }}}Copy the code

Use instance to judge, and then force the Holder class

Public static final int PULLUP_LOAD_MORE = 0;

Public static final int LOADING_MORE = 1;

Private int load_more_status = 0; private int load_more_status = 0;

5. OnScrollStateChanged modification

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);
    load_more_status = LOADING_MORE;
    if (newState == RecyclerView.SCROLL_STATE_IDLE && getCount() + 1 == mAdapter.getItemCount()) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                load_more_status = PULLUP_LOAD_MORE;
                SystemClock.sleep(2000);
                list.addAll(list);
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                        Toast.makeText(getActivity(), "Load complete", Toast.LENGTH_SHORT).show(); }}); } }).start(); }}Copy the code

Iv. Handling of other problems

1. GridLayoutManager adding footView causes layout confusion:

The reason:

GridLayoutManager manager = new GridLayoutManager(getActivity(), 3);

When we were in our new GridLayoutManager, we passed in 3

It’s like dividing a row into 3 parts. By default, each item has 1 part, that is, 3 items in a row, and your footview also has 1 part, so it’s not centered.

Once you know why, it’s easy to change

Public Static Abstract Class SpanSizeLookup (GridLayoutManager package)

The getSpanSize method is overridden when inherited, and returns 1 by default, one layout

class GridSpanSizeLookop extends GridLayoutManager.SpanSizeLookup {
        @Override
        public int getSpanSize(int position) {
            return1; }}Copy the code

So, in this method we can say, when it’s footView, return one line and that’s it.

Modify the return value of the getSpanSize method

class GridSpanSizeLookop extends GridLayoutManager.SpanSizeLookup {
    @Override
    public int getSpanSize(int position) {
//        Log.d(TAG, position + "xx" + list.size() + 1);
        if (position == list.size()) {
            return mManager.getSpanCount();
        }
        return1; }}Copy the code

OnAttachedToRecyclerView ();

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
    if (mGridSpanSizeLookup == null) {
        mGridSpanSizeLookup = new GridSpanSizeLookop();
    }
    mManager.setSpanSizeLookup(mGridSpanSizeLookup);
}
Copy the code

Alternatively, after new GridLayoutManager we can write:

mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        returnposition == list.size() ? mManager.getSpanCount() : 1; }});Copy the code

2. Other uses of getSpanSize:

The following layout is implemented by changing the return value

Code:

mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        returnposition == list.size() ? mManager.getSpanCount() : 3 - position % 3; }});Copy the code

3. The fluid layout processing Due to no setSpanSizeLookup StaggeredGridLayoutManager method, through the load on the way to realize, But StaggeredGridLayoutManager. LayoutParams setFullSpan method can achieve the same effect.

So instead of rewriting the onAttachedToRecyclerView method, we’re rewriting the onViewAttachedToWindow method

@override public void onViewAttachedToWindow(recyclerView.viewholder holder) { super.onViewAttachedToWindow(holder); ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();if(layoutParams ! = null && layoutParams instanceof StaggeredGridLayoutManager. LayoutParams) {/ / is the last oneif (holder.getLayoutPosition() == list.size()) {
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            p.setFullSpan(true); // mIsFresh = can be pulled uptrue; }}}Copy the code