济南APP制作开发 济南APP定制开发 济南手机APP软件制作开发公司

您的位置:首页 > 技术观点 > 信息详情

Android RecyclerView添加上拉加载更多效果

来源:山东鸿软信息科技有限公司  阅读量:  时间:2022-03-25 16:03
这篇文章主要为大家详细介绍了Android RecyclerView添加上拉加载更多效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

先看一下效果
201702241127544.gif

刷新的时候是这样的:

222.png


没有更多的时候是这样的:

3333.png


既然有刷新的时候有两种状态就要定义两个状态:

//普通布局的type

static final int TYPE_ITEM = 0;

//脚布局

static final int TYPE_FOOTER = 1;


在特定的时候去显示:

 @Override

  public int getItemViewType(int position) {

    //如果position加1正好等于所有item的总和,说明是最后一个item,将它设置为脚布局

    if (position + 1 == getItemCount()) {

      return TYPE_FOOTER;

    } else {

      return TYPE_ITEM;

    }

  }



然后根据这个type来inflate不同的布局:

 @Override

  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    if (viewType == TYPE_ITEM) {

      View view = View.inflate(mContext, R.layout.item_recycler, null);

      MyViewHolder holder = new MyViewHolder(view);

      return holder;

    } else if (viewType == TYPE_FOOTER) {

      //脚布局

      View view = View.inflate(mContext, R.layout.recycler_load_more_layout, null);

      FootViewHolder footViewHolder = new FootViewHolder(view);

      return footViewHolder;

    }

    return null;

  }



以上只是控制了Loading布局的出现可隐藏,还要2中状态需要控制就是上面的2个图,一个是正在加载,一个是加载完成状态,这两个状态在adapter里显然是控制不了的,必须要在请求数据的时候才能知道这两种状态,而加载数据又是在activity中执行的,所以我们需要一个用来传递状态的方法:

/**

   * 改变脚布局的状态的方法,在activity根据请求数据的状态来改变这个状态

   *

   * @param state

   */

  public void changeState(int state) {

    this.footer_state = state;

    notifyDataSetChanged();

  }



用来接收状态的变量:

//上拉加载更多

// static final int PULL_LOAD_MORE = 0;

  //正在加载更多

  static final int LOADING_MORE = 1;

  //没有更多

  static final int NO_MORE = 2;

  //脚布局当前的状态,默认为没有更多

  int footer_state = 1;


然后就可以根据这几种状态来控制布局控件的改变了:

 @Override

  public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    if (holder instanceof MyViewHolder) {

      ((MyViewHolder) holder).mTextView.setText(mList.get(position));

    } else if (holder instanceof FootViewHolder) {

      FootViewHolder footViewHolder = (FootViewHolder) holder;

      if (position == 0) {//如果第一个就是脚布局,,那就让他隐藏

        footViewHolder.mProgressBar.setVisibility(View.GONE);

        footViewHolder.tv_line1.setVisibility(View.GONE);

        footViewHolder.tv_line2.setVisibility(View.GONE);

        footViewHolder.tv_state.setText("");

      }

      switch (footer_state) {//根据状态来让脚布局发生改变

//        case PULL_LOAD_MORE://上拉加载

//          footViewHolder.mProgressBar.setVisibility(View.GONE);

//          footViewHolder.tv_state.setText("上拉加载更多");

//          break;

        case LOADING_MORE:

          footViewHolder.mProgressBar.setVisibility(View.VISIBLE);

          footViewHolder.tv_line1.setVisibility(View.GONE);

          footViewHolder.tv_line2.setVisibility(View.GONE);

          footViewHolder.tv_state.setText("正在加载...");

          break;

        case NO_MORE:

          footViewHolder.mProgressBar.setVisibility(View.GONE);

          footViewHolder.tv_line1.setVisibility(View.VISIBLE);

          footViewHolder.tv_line2.setVisibility(View.VISIBLE);

          footViewHolder.tv_state.setText("我是有底线的");

          footViewHolder.tv_state.setTextColor(Color.parseColor("#ff00ff"));

          break;

      }

    }

  }



不要忘了返回的count也要加1,因为添加了一个脚布局:

 @Override

  public int getItemCount() {

    return mList != null ? mList.size() + 1 : 0;

  }



那么什么时候去传递状态到adapter呢?这里就需要给RecyclerView添加滑动监听了,当他滑动到底部的时候显示加载中的状态:

//给recyclerView添加滑动监听

    mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {

      @Override

      public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

        super.onScrollStateChanged(recyclerView, newState);

        /*

        到达底部了,如果不加!isLoading的话到达底部如果还一滑动的话就会一直进入这个方法

        就一直去做请求网络的操作,这样的用户体验肯定不好.添加一个判断,每次滑倒底只进行一次网络请求去请求数据

        当请求完成后,在把isLoading赋值为false,下次滑倒底又能进入这个方法了

         */

        if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount() && !isLoading) {

          //到达底部之后如果footView的状态不是正在加载的状态,就将 他切换成正在加载的状态

          if (page < totlePage) {

            Log.e("duanlian", "onScrollStateChanged: " + "进来了");

            isLoading = true;

            mAdapter.changeState(1);

            new Handler().postDelayed(new Runnable() {

              @Override

              public void run() {

                getData();

                page++;

              }

            }, 2000);

          } else {

            mAdapter.changeState(2);


          }

        }

      }


      @Override

      public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

        super.onScrolled(recyclerView, dx, dy);

        //拿到最后一个出现的item的位置

        lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();

      }

    });


重点就这几个,下面给出脚布局:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:id="@+id/ll_below"

        android:layout_width="match_parent"

        android:layout_height="45dp"

  >


  <LinearLayout

    android:layout_width="fill_parent"

    android:layout_height="45dp"

    android:gravity="center"

    android:orientation="horizontal">


    <TextView

      android:id="@+id/tv_line1"

      android:layout_width="60dp"

      android:layout_height="1dp"

      android:layout_marginRight="10dp"

      android:background="#ff00ff"

      android:visibility="gone"/>


    <ProgressBar

      android:id="@+id/progressbar"

      android:layout_width="25dp"

      android:layout_height="25dp"

      android:visibility="visible"/>


    <TextView

      android:id="@+id/foot_view_item_tv"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:layout_marginLeft="4dp"

      android:text="上拉加载更多"/>


    <TextView

      android:id="@+id/tv_line2"

      android:layout_width="60dp"

      android:layout_height="1dp"

      android:layout_marginLeft="10dp"

      android:background="#ff00ff"

      android:visibility="gone"/>

  </LinearLayout>

</RelativeLayout>



Adapter的代码:

package com.duanlian.recyclerviewloadmoredemo;


import android.content.Context;

import android.graphics.Color;

import android.support.v7.widget.RecyclerView;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ProgressBar;

import android.widget.TextView;


import java.util.List;



public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

  private Context mContext;

  private List<String> mList;

  //普通布局的type

  static final int TYPE_ITEM = 0;

  //脚布局

  static final int TYPE_FOOTER = 1;

  //  //上拉加载更多

//  static final int PULL_LOAD_MORE = 0;

  //正在加载更多

  static final int LOADING_MORE = 1;

  //没有更多

  static final int NO_MORE = 2;

  //脚布局当前的状态,默认为没有更多

  int footer_state = 1;


  public MyRecyclerAdapter(Context context, List<String> list) {

    mContext = context;

    mList = list;

  }


  @Override

  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    if (viewType == TYPE_ITEM) {

      View view = View.inflate(mContext, R.layout.item_recycler, null);

      MyViewHolder holder = new MyViewHolder(view);

      return holder;

    } else if (viewType == TYPE_FOOTER) {

      //脚布局

      View view = View.inflate(mContext, R.layout.recycler_load_more_layout, null);

      FootViewHolder footViewHolder = new FootViewHolder(view);

      return footViewHolder;

    }

    return null;

  }


  @Override

  public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    if (holder instanceof MyViewHolder) {

      ((MyViewHolder) holder).mTextView.setText(mList.get(position));

    } else if (holder instanceof FootViewHolder) {

      FootViewHolder footViewHolder = (FootViewHolder) holder;

      if (position == 0) {//如果第一个就是脚布局,,那就让他隐藏

        footViewHolder.mProgressBar.setVisibility(View.GONE);

        footViewHolder.tv_line1.setVisibility(View.GONE);

        footViewHolder.tv_line2.setVisibility(View.GONE);

        footViewHolder.tv_state.setText("");

      }

      switch (footer_state) {//根据状态来让脚布局发生改变

//        case PULL_LOAD_MORE://上拉加载

//          footViewHolder.mProgressBar.setVisibility(View.GONE);

//          footViewHolder.tv_state.setText("上拉加载更多");

//          break;

        case LOADING_MORE:

          footViewHolder.mProgressBar.setVisibility(View.VISIBLE);

          footViewHolder.tv_line1.setVisibility(View.GONE);

          footViewHolder.tv_line2.setVisibility(View.GONE);

          footViewHolder.tv_state.setText("正在加载...");

          break;

        case NO_MORE:

          footViewHolder.mProgressBar.setVisibility(View.GONE);

          footViewHolder.tv_line1.setVisibility(View.VISIBLE);

          footViewHolder.tv_line2.setVisibility(View.VISIBLE);

          footViewHolder.tv_state.setText("我是有底线的");

          footViewHolder.tv_state.setTextColor(Color.parseColor("#ff00ff"));

          break;

      }

    }

  }



  @Override

  public int getItemViewType(int position) {

    //如果position加1正好等于所有item的总和,说明是最后一个item,将它设置为脚布局

    if (position + 1 == getItemCount()) {

      return TYPE_FOOTER;

    } else {

      return TYPE_ITEM;

    }

  }


  @Override

  public int getItemCount() {

    return mList != null ? mList.size() + 1 : 0;

  }


  /**

   * 正常布局的ViewHolder

   */

  class MyViewHolder extends RecyclerView.ViewHolder {

    TextView mTextView;


    public MyViewHolder(View itemView) {

      super(itemView);

      mTextView = (TextView) itemView.findViewById(R.id.item_textView);

    }

  }


  /**

   * 脚布局的ViewHolder

   */

  public static class FootViewHolder extends RecyclerView.ViewHolder {

    private ProgressBar mProgressBar;

    private TextView tv_state;

    private TextView tv_line1;

    private TextView tv_line2;



    public FootViewHolder(View itemView) {

      super(itemView);

      mProgressBar = (ProgressBar) itemView.findViewById(R.id.progressbar);

      tv_state = (TextView) itemView.findViewById(R.id.foot_view_item_tv);

      tv_line1 = (TextView) itemView.findViewById(R.id.tv_line1);

      tv_line2 = (TextView) itemView.findViewById(R.id.tv_line2);


    }

  }


  /**

   * 改变脚布局的状态的方法,在activity根据请求数据的状态来改变这个状态

   *

   * @param state

   */

  public void changeState(int state) {

    this.footer_state = state;

    notifyDataSetChanged();

  }


}


activity中的代码:

package com.duanlian.recyclerviewloadmoredemo;


import android.os.Bundle;

import android.os.Handler;

import android.support.v7.app.AppCompatActivity;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.util.Log;


import java.util.ArrayList;

import java.util.List;


public class MainActivity extends AppCompatActivity {


  private RecyclerView mRecycler;

  private List<String> mList;

  private List<String> list;

  private MyRecyclerAdapter mAdapter;

  LinearLayoutManager linearLayoutManager;

  int lastVisibleItem;

  int page = 0;

  boolean isLoading = false;//用来控制进入getdata()的次数

  int totlePage = 5;//模拟请求的一共的页数


  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    initView();

    getData();

  }


  private void initView() {

    mRecycler = (RecyclerView) findViewById(R.id.recycler);

    linearLayoutManager = new LinearLayoutManager(this);

    mRecycler.setLayoutManager(linearLayoutManager);

    mList = new ArrayList<>();

    mAdapter = new MyRecyclerAdapter(this, mList);

    mRecycler.setAdapter(mAdapter);

    //给recyclerView添加滑动监听

    mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {

      @Override

      public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

        super.onScrollStateChanged(recyclerView, newState);

        /*

        到达底部了,如果不加!isLoading的话到达底部如果还一滑动的话就会一直进入这个方法

        就一直去做请求网络的操作,这样的用户体验肯定不好.添加一个判断,每次滑倒底只进行一次网络请求去请求数据

        当请求完成后,在把isLoading赋值为false,下次滑倒底又能进入这个方法了

         */

        if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount() && !isLoading) {

          //到达底部之后如果footView的状态不是正在加载的状态,就将 他切换成正在加载的状态

          if (page < totlePage) {

            Log.e("duanlian", "onScrollStateChanged: " + "进来了");

            isLoading = true;

            mAdapter.changeState(1);

            new Handler().postDelayed(new Runnable() {

              @Override

              public void run() {

                getData();

                page++;

              }

            }, 2000);

          } else {

            mAdapter.changeState(2);


          }

        }

      }


      @Override

      public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

        super.onScrolled(recyclerView, dx, dy);

        //拿到最后一个出现的item的位置

        lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();

      }

    });


  }


  /**

   * 模拟请求数据

   */

  private void getData() {

    list = new ArrayList<>();

    for (int i = 0; i < 10; i++) {

      list.add("第" + i + "条");

    }

    mList.addAll(list);

    isLoading = false;

    mAdapter = new MyRecyclerAdapter(this, mList);

    mRecycler.setAdapter(mAdapter);

  }

}


以上就是本文的全部内容,希望对大家的学习有所帮助。

成为您更加专业的技术合伙人

APP开发 | 网站建设 | 产品服务 | 技术观点 | 关于我们      客服电子邮箱:1828087588@qq.com  客服QQ:1828087588、1421667633  电话:151-6502-2080

Copyright © 2016 山东鸿软信息科技有限公司 版权所有 https://www.greatsoft.cc 鲁ICP备16026454号