Android RecyclerView添加上拉加載更多效果
先看一下效果
刷新的時(shí)候是這樣的:
沒有更多的時(shí)候是這樣的:
既然有刷新的時(shí)候有兩種狀態(tài)就要定義兩個(gè)狀態(tài)
//普通布局的type static final int TYPE_ITEM = 0; //腳布局 static final int TYPE_FOOTER = 1;
在特定的時(shí)候去顯示:
@Override public int getItemViewType(int position) { //如果position加1正好等于所有item的總和,說明是最后一個(gè)item,將它設(shè)置為腳布局 if (position + 1 == getItemCount()) { return TYPE_FOOTER; } else { return TYPE_ITEM; } }
然后根據(jù)這個(gè)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布局的出現(xiàn)可隱藏,還要2中狀態(tài)需要控制就是上面的2個(gè)圖,一個(gè)是正在加載,一個(gè)是加載完成狀態(tài),這兩個(gè)狀態(tài)在adapter里顯然是控制不了的,必須要在請(qǐng)求數(shù)據(jù)的時(shí)候才能知道這兩種狀態(tài),而加載數(shù)據(jù)又是在activity中執(zhí)行的,所以我們需要一個(gè)用來傳遞狀態(tài)的方法:
/** * 改變腳布局的狀態(tài)的方法,在activity根據(jù)請(qǐng)求數(shù)據(jù)的狀態(tài)來改變這個(gè)狀態(tài) * * @param state */ public void changeState(int state) { this.footer_state = state; notifyDataSetChanged(); }
用來接收狀態(tài)的變量:
//上拉加載更多 // static final int PULL_LOAD_MORE = 0; //正在加載更多 static final int LOADING_MORE = 1; //沒有更多 static final int NO_MORE = 2; //腳布局當(dāng)前的狀態(tài),默認(rèn)為沒有更多 int footer_state = 1;
然后就可以根據(jù)這幾種狀態(tài)來控制布局控件的改變了:
@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) {//如果第一個(gè)就是腳布局,,那就讓他隱藏 footViewHolder.mProgressBar.setVisibility(View.GONE); footViewHolder.tv_line1.setVisibility(View.GONE); footViewHolder.tv_line2.setVisibility(View.GONE); footViewHolder.tv_state.setText(""); } switch (footer_state) {//根據(jù)狀態(tài)來讓腳布局發(fā)生改變 // 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,因?yàn)樘砑恿艘粋€(gè)腳布局:
@Override public int getItemCount() { return mList != null ? mList.size() + 1 : 0; }
那么什么時(shí)候去傳遞狀態(tài)到adapter呢?這里就需要給RecyclerView添加滑動(dòng)監(jiān)聽了,當(dāng)他滑動(dòng)到底部的時(shí)候顯示加載中的狀態(tài):
//給recyclerView添加滑動(dòng)監(jiān)聽 mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); /* 到達(dá)底部了,如果不加!isLoading的話到達(dá)底部如果還一滑動(dòng)的話就會(huì)一直進(jìn)入這個(gè)方法 就一直去做請(qǐng)求網(wǎng)絡(luò)的操作,這樣的用戶體驗(yàn)肯定不好.添加一個(gè)判斷,每次滑倒底只進(jìn)行一次網(wǎng)絡(luò)請(qǐng)求去請(qǐng)求數(shù)據(jù) 當(dāng)請(qǐng)求完成后,在把isLoading賦值為false,下次滑倒底又能進(jìn)入這個(gè)方法了 */ if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount() && !isLoading) { //到達(dá)底部之后如果footView的狀態(tài)不是正在加載的狀態(tài),就將 他切換成正在加載的狀態(tài) if (page < totlePage) { Log.e("duanlian", "onScrollStateChanged: " + "進(jìn)來了"); 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); //拿到最后一個(gè)出現(xiàn)的item的位置 lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); } });
重點(diǎn)就這幾個(gè),下面給出腳布局:
<?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; //腳布局當(dāng)前的狀態(tài),默認(rèn)為沒有更多 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) {//如果第一個(gè)就是腳布局,,那就讓他隱藏 footViewHolder.mProgressBar.setVisibility(View.GONE); footViewHolder.tv_line1.setVisibility(View.GONE); footViewHolder.tv_line2.setVisibility(View.GONE); footViewHolder.tv_state.setText(""); } switch (footer_state) {//根據(jù)狀態(tài)來讓腳布局發(fā)生改變 // 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的總和,說明是最后一個(gè)item,將它設(shè)置為腳布局 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); } } /** * 改變腳布局的狀態(tài)的方法,在activity根據(jù)請(qǐng)求數(shù)據(jù)的狀態(tài)來改變這個(gè)狀態(tài) * * @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;//用來控制進(jìn)入getdata()的次數(shù) int totlePage = 5;//模擬請(qǐng)求的一共的頁數(shù) @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添加滑動(dòng)監(jiān)聽 mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); /* 到達(dá)底部了,如果不加!isLoading的話到達(dá)底部如果還一滑動(dòng)的話就會(huì)一直進(jìn)入這個(gè)方法 就一直去做請(qǐng)求網(wǎng)絡(luò)的操作,這樣的用戶體驗(yàn)肯定不好.添加一個(gè)判斷,每次滑倒底只進(jìn)行一次網(wǎng)絡(luò)請(qǐng)求去請(qǐng)求數(shù)據(jù) 當(dāng)請(qǐng)求完成后,在把isLoading賦值為false,下次滑倒底又能進(jìn)入這個(gè)方法了 */ if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount() && !isLoading) { //到達(dá)底部之后如果footView的狀態(tài)不是正在加載的狀態(tài),就將 他切換成正在加載的狀態(tài) if (page < totlePage) { Log.e("duanlian", "onScrollStateChanged: " + "進(jìn)來了"); 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); //拿到最后一個(gè)出現(xiàn)的item的位置 lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); } }); } /** * 模擬請(qǐng)求數(shù)據(jù) */ 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); } }
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android ExpandableListView實(shí)現(xiàn)下拉刷新和加載更多效果
- Android實(shí)踐之帶加載效果的下拉刷新上拉加載更多
- android使用PullToRefresh框架實(shí)現(xiàn)ListView下拉刷新上拉加載更多
- Android中使用ScrollView實(shí)現(xiàn)滑動(dòng)到底部顯示加載更多
- Android中RecycleView與ViewPager沖突的解決方法及原理
- Android RecycleView使用(CheckBox全選、反選、單選)
- android中RecycleView添加下滑到底部的監(jiān)聽示例
- Android 使用RecycleView列表實(shí)現(xiàn)加載更多的示例代碼
相關(guān)文章
android 選項(xiàng)卡(TabHost)如何放置在屏幕的底部
如何將TAB放置在屏幕的底端,有很多的新手都想實(shí)現(xiàn)這種效果,本文搜集整理了一些,感興趣的朋友可以參考下哦2013-01-01android電源信息查看(電量、溫度、電壓)實(shí)例代碼
這篇文章主要介紹了android電源信息查看方法,以實(shí)例形式較為詳細(xì)的分析了Android實(shí)現(xiàn)電源電量、電壓、溫度等信息查看的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10Android Studio實(shí)現(xiàn)幀動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了Android Studio實(shí)現(xiàn)幀動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Android CameraX結(jié)合LibYUV和GPUImage自定義相機(jī)濾鏡
之前使用Camera實(shí)現(xiàn)了一個(gè)自定義相機(jī)濾鏡(Android自定義相機(jī)濾鏡 ),但是運(yùn)行起來有點(diǎn)卡頓,這次用Camerax來實(shí)現(xiàn)一樣的效果發(fā)現(xiàn)很流暢,在此記錄一下,也希望能幫到有需要的同學(xué)2021-12-12Android Fragment滑動(dòng)組件ViewPager的實(shí)例詳解
這篇文章主要介紹了Android Fragment滑動(dòng)組件ViewPager的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05Android控件系列之RadioButton與RadioGroup使用方法
本文介紹了Android中如何使用RadioGroup和RadioButton,對(duì)比了RadioButton和CheckBox的區(qū)別,并實(shí)現(xiàn)了自定義的RadioGroup中被選中RadioButton的變更監(jiān)聽事件2012-11-11Android使用ViewPager完成app引導(dǎo)頁
這篇文章主要為大家詳細(xì)介紹了Android使用ViewPager完成app引導(dǎo)頁,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫的方法
這篇文章主要介紹了android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03