重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
在Android项目中使用RecyclerView实现一个上拉加载更多功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
目前成都创新互联已为上千的企业提供了网站建设、域名、网络空间、网站托管、企业网站设计、武安网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
既然有刷新的时候有两种状态就要定义两个状态
//普通布局的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"?>
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{ private Context mContext; private List 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 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 ListmList; private List 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); } }
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注创新互联行业资讯频道,感谢您对创新互联的支持。