去年在大神公眾號評論點(diǎn)贊前三名獲得了《Android App開發(fā)從入門到精通》這本書窖壕,這兩天閑來無事忧勿,就大致瀏覽一下書的內(nèi)容杉女。看到了關(guān)于recycleView部分鸳吸,提到了一些關(guān)于recycleView自己會(huì)用但是不知道為啥這么用的的知識(shí)熏挎,就抽個(gè)周日的時(shí)間,根據(jù)書上的東西晌砾,敲了敲代碼坎拐,收獲還是不少的,再次記錄下來养匈,希望留著以后備用哼勇,能幫到更多的人最好,爭取不誤人子弟哈(偷笑)
廢話不多說呕乎,進(jìn)入正題积担,這篇文章分為以下幾個(gè)部分層層遞進(jìn):
- recycleView 基礎(chǔ)使用;
- recycleView 添加分割線猬仁;
- recycleView 添加頭布局和尾布局帝璧;
- recycleView 數(shù)據(jù)刪除item動(dòng)畫實(shí)現(xiàn);
- recycleView 下拉刷新和上拉加載湿刽;
一:recycleView 基礎(chǔ)使用
思路如下:
1: recycleView 初始化并設(shè)置layouManager
RecyclerView mRecycleView=findViewById(R.id.mRecycleView);
//按照listView垂直方向使用的烁;
mRecycleView.setLayoutManager(new LinearLayoutManager(this));
/**
* 卡片式布局
* 一行四列;
* 第三個(gè)參數(shù)(reverseLayout) 表示的是是否將數(shù)據(jù)按照倒敘進(jìn)行展示叭爱,
* false表示 1234 這樣展示撮躁;
* 5678
* 9
true 表示:9 這樣展示;
* 8765
* 4321
* 第三個(gè)參數(shù)開發(fā)這么多年买雾,一般都是false,不知道谷歌為啥要多整個(gè)這個(gè)
*/
mRecycleView.setLayoutManager(new GridLayoutManager(this, 4,GridLayoutManager.VERTICAL,false));
/**
* 表示所有數(shù)據(jù)總共就四行進(jìn)行展示
* */
mRecycleView.setLayoutManager(new GridLayoutManager(this, 4,GridLayoutManager.HORIZONTAL,false));
/**
* 瀑布流把曼,方向參考gridView;
*/
mRecycleView.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));
2: 編寫adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
Context context;
List<ItemBean>lists;
public MyAdapter(Context context,List<ItemBean>lists) {
this.context = context;
this.lists=lists;
}
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// //這樣寫的話,itemView不能鋪滿漓穿,不知道為啥
// //例如說:recycleView作為listView使用嗤军,item水平上就不能充滿屏幕
// View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,null);
//這種方式就可以充滿屏幕
View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,parent,false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyAdapter.MyViewHolder holder, final int position) {
holder.mTv.setText(bean.getName());
}
@Override
public int getItemCount() {
return lists.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder{
TextView mTv;
public MyViewHolder(View itemView) {
super(itemView);
mTv=itemView.findViewById(R.id.mTv);
}
}
}
3:獲取數(shù)據(jù)源并設(shè)置adapter;
List<ItemBean> lists=new ArrayList<>();
for (int i = 0; i <54 ; i++) {
ItemBean b=new ItemBean();
b.setName("編號"+i);
b.setHeight(i*50+10);
lists.add(b);
}
MyAdapter adapter = new MyAdapter(this, lists,this);
mRecycleView.setAdapter(adapter);
這就是關(guān)于cecycleView 的基礎(chǔ)使用,基本上用過recycleView的兄臺(tái)們晃危,都對這部分熟悉的不能再熟悉了叙赚,但是有幾點(diǎn)細(xì)節(jié)需要注意:
細(xì)節(jié)點(diǎn):
- recycleView設(shè)置adapter之前一定要記得設(shè)置layoutManager(),否則數(shù)據(jù)不展示,沒有任何異常僚饭;
- adapter中onCreateViewHolder方法中注釋詳解
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// /**
* 這樣寫的話震叮,如果是垂直方向上的recycleView(listView),item水平方向上是不能充滿屏幕的,具體原因不知
* 可以自己試試鳍鸵;
*
*/
// View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,null);
/**
* //這種方式就可以充滿屏幕苇瓣,解決上面提到的問題
* /**
* recource 布局文件資源id
* root 父View
* attachToRoot
* true 布局文件將轉(zhuǎn)化為View 并綁定到root,然后返回root作為根節(jié)點(diǎn)的整個(gè)View
* false 布局文件將轉(zhuǎn)化為View 不綁定到root ,然后返回以布局文件根節(jié)點(diǎn)作為根節(jié)點(diǎn)的View
*/
View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,parent,false);
return new MyViewHolder(itemView);
}
二 recycleView 添加分割線
思路如下:
recycleView添加分割線,我認(rèn)為主要有三種方式:
1:分割線divider在item中添加偿乖,根據(jù)item的位置索引position動(dòng)態(tài)設(shè)置divider的顯示和隱藏击罪。例如 recycleView作為listView使用哲嘲,item位于中間部分divider可以正常展示,最后一個(gè)item的divider可以根據(jù)實(shí)際情況進(jìn)行顯示和隱藏媳禁;
2:設(shè)置默認(rèn)分割線
mRecyclerView.addItemDecoration(new RecycleViewDivider(mContext, LinearLayoutManager.VERTICAL));
這種方式眠副,分割線顏色和寬度高度等都是不可控的,不是很實(shí)用竣稽;
3:對RecyclerView.ItemDecoration進(jìn)行重寫囱怕,等同于自定義,自己實(shí)現(xiàn)測量繪制布局等方法丧枪,實(shí)現(xiàn)起來對于類似我這樣基礎(chǔ)的同學(xué)還是比較困難的(書中有詳細(xì)代碼光涂,時(shí)間有限,我懶得看)拧烦。
總結(jié)
以上三種方法忘闻,個(gè)人比較傾向于第一種,為啥類恋博,因?yàn)橐撞僮髌爰眩蓪?shí)現(xiàn)性強(qiáng),唯一缺點(diǎn)就是adapter中增加了item下標(biāo)位置的邏輯判斷债沮。
參考文章 recycleView設(shè)置分割線的三種方式
三 recycleView 添加頭布局和尾布局
思路總結(jié)
日常開發(fā)中炼吴,我們經(jīng)常遇到這樣的情況,app首頁上半部分是個(gè)Banner疫衩,中間部分是一個(gè)列表(recycleView)展示數(shù)據(jù)硅蹦,下半部分展示一些其他信息,實(shí)現(xiàn)這樣一個(gè)整體部分方法有兩種:
- scrollView 嵌套R(shí)ecycleView 并且需要暴力解決嵌套出現(xiàn)的一些滑動(dòng)沖突闷煤,數(shù)據(jù)展示不全等問題童芹,可以參考我的另外一篇雜記(東西比較多羽峰,比較亂哈)中關(guān)于recycleView部分篷牌;
- 再就是以recycleView作為主體,為其添加頭布局和尾布局杂抽;繼續(xù)思考近顷,為什么需要單獨(dú)添加頭布局和尾布局呢生音,為啥不能按照正常的item進(jìn)行使用呢?你可能投來一臉的鄙視窒升,然后說:“頭布局/尾布局/item布局顯示不一樣啊”缀遍。好吧,我接受你的鄙視饱须,問了個(gè)白癡問題瑟由,順著這個(gè)思路往下走,為recycleView 添加頭布局和尾布局的效果,是否可以理解為等同于為recycleView添加不一樣布局的item歹苦?只不過就是頭部,尾部督怜,中間部分三部分不一樣而已殴瘦。那這和使用recycleView實(shí)現(xiàn)對話列表的思路是不是一致呢?對嘍:鸥堋r揭浮!兩種實(shí)現(xiàn)思路是一樣的(慚愧姨蟋,我是寫這篇文章的時(shí)候突然才意識(shí)到這個(gè)問題)屉凯。參考recycleView 添加不同的item.看完參考文章,相信大體思路都應(yīng)該有了眼溶,下面受累看一下添加頭布局和尾布局的代碼
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
List<ItemBean>lists;
private RecycleViewItemClickCallBack clickCallBack;
public static final int TYPE_HEADER=1;
public static final int TYPE_FOOTER=2;
private View headView;
private View footView;
public MyAdapter(Context context,List<ItemBean>lists,RecycleViewItemClickCallBack callBack) {
this.context = context;
this.lists=lists;
this.clickCallBack=callBack;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType==TYPE_HEADER){
return new RecyclerView.ViewHolder(headView){};
}else if(viewType==TYPE_FOOTER){
return new RecyclerView.ViewHolder(footView){};
}else{
/**
* 這樣寫的話悠砚,如果是垂直方向上的recycleView(listView),item水平方向上是不能充滿屏幕的,具體原因不知
* 可以自己試試堂飞;
*
*/
// View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,null);
/**
* //這種方式就可以充滿屏幕灌旧,解決上面提到的問題
* /**
* recource 布局文件資源id
* root 父View
* attachToRoot
* true 布局文件將轉(zhuǎn)化為View 并綁定到root,然后返回root作為根節(jié)點(diǎn)的整個(gè)View
* false 布局文件將轉(zhuǎn)化為View 不綁定到root ,然后返回以布局文件根節(jié)點(diǎn)作為根節(jié)點(diǎn)的View
*/
View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,parent,false);
return new MyViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if(getItemViewType(position)==TYPE_FOOTER||getItemViewType(position)==TYPE_HEADER){
return;
}
final MyViewHolder myViewHolder= (MyViewHolder) holder;
ItemBean bean=lists.get(getRealPosition(position));
myViewHolder.mTv.setText(bean.getName());
myViewHolder.mTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickCallBack.onItemClick(position,myViewHolder.mTv,getRealPosition(position));
}
});
}
private int getRealPosition(int position) {
return headView==null?position:position-1;
}
@Override
public int getItemViewType(int position) {
if(position==0&&headView!=null){
return TYPE_HEADER;
}else if(position==getItemCount()-1&&footView!=null){
return TYPE_FOOTER;
}
return super.getItemViewType(position);
}
@Override
public int getItemCount() {
if(headView==null&&footView==null){
return lists.size();
}else if((headView==null&&footView!=null)||(headView!=null&&footView==null)){
return lists.size()+1;
}else{
return lists.size()+2;
}
}
static class MyViewHolder extends RecyclerView.ViewHolder{
TextView mTv;
public MyViewHolder(View itemView) {
super(itemView);
mTv=itemView.findViewById(R.id.mTv);
}
}
public void setHeadView(RecyclerView mrecycleView,int reasouceId){
/**
* recource 布局文件資源id
* root 父View
* attachToRoot
* true 布局文件將轉(zhuǎn)化為View 并綁定到root,然后返回root作為根節(jié)點(diǎn)的整個(gè)View
* false 布局文件將轉(zhuǎn)化為View 不綁定到root ,然后返回以布局文件根節(jié)點(diǎn)作為根節(jié)點(diǎn)的View
*/
View headView = LayoutInflater.from(context).inflate(reasouceId,mrecycleView,false);
this.headView=headView;
notifyItemInserted(0);
}
public void setFontView(RecyclerView mrecycleView,int reasouceId){
View footView = LayoutInflater.from(context).inflate(reasouceId,mrecycleView,false);
this.footView=headView;
this.footView=footView;
notifyItemInserted(headView==null?lists.size()-1:lists.size());
}
public interface RecycleViewItemClickCallBack{
void onItemClick(int position,View mView,int realClickPosition);
}
}
細(xì)節(jié)歸納
- getItemViewType()方法用于區(qū)別返回不同的item類型;對應(yīng) onCreateViewHolder(ViewGroup parent, int viewType) {}參數(shù)中的viewType绰筛,可以根據(jù)該參數(shù)區(qū)別加載不同的item;
- 另外書中重點(diǎn)點(diǎn)出了加載頭布局和尾布局要使用
View footView = LayoutInflater.from(context).inflate(reasouceId,mrecycleView,false);
看到這里枢泰,我一直在考慮之前試圖添加頭布局和尾布局總失敗的原因是不是因?yàn)槲沂褂玫氖?/p>
View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,null);
我沒有詳細(xì)測這里,小伙伴們可以自己看看自己的代碼铝噩,驗(yàn)證一下這里衡蚂,日常開發(fā)中也要注意這里。
四 recycleView 數(shù)據(jù)刪除item動(dòng)畫實(shí)現(xiàn)
關(guān)鍵代碼如下:
Toast.makeText(this,"點(diǎn)擊的是"+realClickPosition,Toast.LENGTH_LONG).show();
/**
* recycleView刪除數(shù)據(jù)的方法步驟如下:
* 1:刪除原有數(shù)據(jù)源數(shù)據(jù)骏庸;
* 2:adapter毛甲。notifyItemRemoved(指定位置的index);adapter通知指定位置的item進(jìn)行刪除操作;
* 3:adapter.notifyItemRangeChanged(刪除位置的index敞恋,以及到最后的數(shù)據(jù)長度)adapter通知后面的item進(jìn)行調(diào)整補(bǔ)齊
*/
//移除數(shù)據(jù)源
lists.remove(realClickPosition);
//item 移除動(dòng)畫
adapter.notifyItemRemoved(position);
/**
* 第一個(gè)參數(shù)是變化的item七點(diǎn)位置index;
* 第二個(gè)參數(shù)是從idex必須變化的長度丽啡;
* 比方說總item 10 ,index=5,那么必須變化的長度就是5后面的item硬猫,也就是10-5-1=4补箍;
*/
adapter.notifyItemRangeChanged(position,adapter.getItemCount()-position-1);
以后列表刪除數(shù)據(jù),不用整體刷新了啸蜜,可以考慮用這種方法坑雅,還有動(dòng)畫效果Nice。
五 recycleView 下拉刷新和上拉加載
思路歸納
- 實(shí)現(xiàn)下拉刷新可以使用系統(tǒng)自帶的SwipeRefreshLayout衬横,包裹recycleView實(shí)現(xiàn)下拉刷新裹粤;
- 上拉加載系統(tǒng)沒有可以直接使用的控件,只能自己實(shí)現(xiàn)蜂林;
- recycleView添加footer布局遥诉,布局里面包含進(jìn)度條拇泣,模擬加載更多效果(這里可以自定義,根據(jù)自己需求來)
- recycleView 添加setOnScrollListener監(jiān)聽矮锈,在監(jiān)聽 中判斷recycleView是否滑動(dòng)到底部霉翔,從而決定是否加載更多,加載更多數(shù)據(jù)之前foot布局中的進(jìn)度條展示苞笨,數(shù)據(jù)加載完了之后進(jìn)行隱藏债朵;
- 根據(jù)實(shí)現(xiàn)上拉加載更多的思路同樣可以實(shí)現(xiàn)下拉刷新的功能(就不需求SwipeRefreshLayout包裹了),這種實(shí)現(xiàn)方式瀑凝,可配置性比較高序芦,完全可以根據(jù)需求進(jìn)行刷新和加載更多布局展示。
具體代碼如下
主布局xml部分
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mSr"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.bcj.myrecycleview.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/mRecycleView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</android.support.v4.widget.SwipeRefreshLayout>
頭布局和尾布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:background="#f00"
android:id="@+id/mTv"
android:text="這是頭布局哈哈"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="50dp" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="#ff0"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:gravity="center"
android:layout_gravity="center_horizontal"
android:text="這是尾布局哈哈"
android:layout_width="wrap_content"
android:layout_height="50dp" />
<ProgressBar
android:id="@+id/mTv_foot"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="50dp" />
</LinearLayout>
java代碼部分
public class MainActivity extends AppCompatActivity implements MyAdapter.RecycleViewItemClickCallBack,
SwipeRefreshLayout.OnRefreshListener{
List<ItemBean> lists=new ArrayList<>();
private MyAdapter adapter;
private ProgressBar pb;
private Handler mHandler=new Handler();
private View footView;
private SwipeRefreshLayout mSr;
RecyclerView mRecycleView;
private int refrashNum=4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecycleView=findViewById(R.id.mRecycleView);
mSr=findViewById(R.id.mSr);
mRecycleView.setLayoutManager(new LinearLayoutManager(this));
footView = LayoutInflater.from(this).inflate(R.layout.foot_item_layout, mRecycleView,false);
pb=footView.findViewById(R.id.mTv_foot);
pb.setVisibility(View.GONE);
mSr.setColorSchemeResources(R.color.colorAccent,android.R.color.holo_blue_light, R.color.colorPrimary);
mSr.setRefreshing(true);
initLists();
setListener();
}
private void setAdapter() {
if(adapter==null){
adapter = new MyAdapter(this, lists,this);
adapter.setHeadView(mRecycleView,R.layout.head_item_layout);
adapter.setFontView(mRecycleView,footView);
mRecycleView.setAdapter(adapter);
}else{
adapter.notifyDataSetChanged();
}
}
private void setListener() {
mSr.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
initLists();
}
});
mRecycleView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
RecyclerView.LayoutManager mLm=recyclerView.getLayoutManager();
int lastVisibleItem=((LinearLayoutManager)mLm).findLastVisibleItemPosition();
int totalItemCount=mLm.getItemCount();
//最后一項(xiàng)顯示&&下滑狀態(tài)的時(shí)候回調(diào)加載更多
if(pb.getVisibility()==View.GONE&&lastVisibleItem>=totalItemCount-1&&dy>0){
pb.setVisibility(View.VISIBLE);
loadMoreInfo();
}
}
});
}
private void loadMoreInfo() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
pb.setVisibility(View.GONE);
for (int i = 0; i <5 ; i++) {
ItemBean b=new ItemBean();
b.setName("加載更多"+i);
lists.add(b);
}
setAdapter();
}
},1000);
}
private void initLists() {
lists.clear();
refrashNum++;
for (int i = 0; i <refrashNum+6 ; i++) {
ItemBean b=new ItemBean();
b.setName("編號"+i);
b.setHeight(i*50+10);
lists.add(b);
}
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
setAdapter();
mSr.setRefreshing(false);
}
},1000);
}
@Override
public void onItemClick(int position, View mView, int realClickPosition) {
Toast.makeText(this,"點(diǎn)擊的是"+realClickPosition,Toast.LENGTH_LONG).show();
/**
* recycleView刪除數(shù)據(jù)的方法步驟如下:
* 1:刪除原有數(shù)據(jù)源數(shù)據(jù)粤咪;
* 2:adapter谚中。notifyItemRemoved(指定位置的index);adapter通知指定位置的item進(jìn)行刪除操作;
* 3:adapter.notifyItemRangeChanged(刪除位置的index射窒,以及到最后的數(shù)據(jù)長度)adapter通知后面的item進(jìn)行調(diào)整補(bǔ)齊
*/
//移除數(shù)據(jù)源
lists.remove(realClickPosition);
//item 移除動(dòng)畫
adapter.notifyItemRemoved(position);
/**
* 第一個(gè)參數(shù)是變化的item七點(diǎn)位置index;
* 第二個(gè)參數(shù)是從idex必須變化的長度藏杖;
* 比方說總item 10 ,index=5,那么必須變化的長度就是5后面的item脉顿,也就是10-5-1=4蝌麸;
*/
adapter.notifyItemRangeChanged(position,adapter.getItemCount()-position-1);
}
@Override
public void onRefresh() {
}
}
adapter 部分
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
List<ItemBean>lists;
private RecycleViewItemClickCallBack clickCallBack;
public static final int TYPE_HEADER=1;
public static final int TYPE_FOOTER=2;
private View headView;
private View footView;
public MyAdapter(Context context,List<ItemBean>lists,RecycleViewItemClickCallBack callBack) {
this.context = context;
this.lists=lists;
this.clickCallBack=callBack;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType==TYPE_HEADER){
return new RecyclerView.ViewHolder(headView){};
}else if(viewType==TYPE_FOOTER){
return new RecyclerView.ViewHolder(footView){};
}else{
/**
* 這樣寫的話,如果是垂直方向上的recycleView(listView),item水平方向上是不能充滿屏幕的艾疟,具體原因不知
* 可以自己試試来吩;
*
*/
// View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,null);
/**
* //這種方式就可以充滿屏幕,解決上面提到的問題
* /**
* recource 布局文件資源id
* root 父View
* attachToRoot
* true 布局文件將轉(zhuǎn)化為View 并綁定到root,然后返回root作為根節(jié)點(diǎn)的整個(gè)View
* false 布局文件將轉(zhuǎn)化為View 不綁定到root ,然后返回以布局文件根節(jié)點(diǎn)作為根節(jié)點(diǎn)的View
*/
View itemView= LayoutInflater.from(context).inflate(R.layout.item_layout,parent,false);
return new MyViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if(getItemViewType(position)==TYPE_FOOTER||getItemViewType(position)==TYPE_HEADER){
return;
}
final MyViewHolder myViewHolder= (MyViewHolder) holder;
ItemBean bean=lists.get(getRealPosition(position));
myViewHolder.mTv.setText(bean.getName());
myViewHolder.mTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickCallBack.onItemClick(position,myViewHolder.mTv,getRealPosition(position));
}
});
}
private int getRealPosition(int position) {
return headView==null?position:position-1;
}
@Override
public int getItemViewType(int position) {
if(position==0&&headView!=null){
return TYPE_HEADER;
}else if(position==getItemCount()-1&&footView!=null){
return TYPE_FOOTER;
}
return super.getItemViewType(position);
}
@Override
public int getItemCount() {
if(headView==null&&footView==null){
return lists.size();
}else if((headView==null&&footView!=null)||(headView!=null&&footView==null)){
return lists.size()+1;
}else{
return lists.size()+2;
}
}
static class MyViewHolder extends RecyclerView.ViewHolder{
TextView mTv;
public MyViewHolder(View itemView) {
super(itemView);
mTv=itemView.findViewById(R.id.mTv);
}
}
public void setHeadView(RecyclerView mrecycleView,int reasouceId){
/**
* recource 布局文件資源id
* root 父View
* attachToRoot
* true 布局文件將轉(zhuǎn)化為View 并綁定到root,然后返回root作為根節(jié)點(diǎn)的整個(gè)View
* false 布局文件將轉(zhuǎn)化為View 不綁定到root ,然后返回以布局文件根節(jié)點(diǎn)作為根節(jié)點(diǎn)的View
*/
View headView = LayoutInflater.from(context).inflate(reasouceId,mrecycleView,false);
this.headView=headView;
notifyItemInserted(0);
}
public void setFontView(RecyclerView mrecycleView,View footView){
this.footView=headView;
this.footView=footView;
notifyItemInserted(headView==null?lists.size()-1:lists.size());
}
public interface RecycleViewItemClickCallBack{
void onItemClick(int position,View mView,int realClickPosition);
}
}
代碼基本思路如下:
- 對控件初始化蔽莱,做相應(yīng)的設(shè)置弟疆,頭布局尾布局初始化,隱層尾布局的進(jìn)度條盗冷;
- 進(jìn)入頁面手動(dòng)刷新怠苔,加載數(shù)據(jù),延遲1s模擬網(wǎng)絡(luò)請求仪糖,加載數(shù)據(jù)柑司,停止刷新(每次刷新都在原有基礎(chǔ)上增加一條數(shù)據(jù),區(qū)別刷新前后)锅劝;
- recycleView.setOnScrollListener,監(jiān)聽中判斷是否滑動(dòng)到最底部攒驰,進(jìn)而決定是否加載更多;
總結(jié):
我個(gè)人覺得這一部分的關(guān)鍵點(diǎn)是recycleView.setOnScrollListener()監(jiān)聽中的邏輯判斷故爵,這里是實(shí)現(xiàn)上拉加載更多的關(guān)鍵地方玻粪,有沒有小伙伴想到用這種方式實(shí)現(xiàn)下拉刷新呢?我之前也是認(rèn)為可以實(shí)現(xiàn)的,但是真正去嘗試去試著實(shí)現(xiàn)的時(shí)候劲室,發(fā)現(xiàn)不太現(xiàn)實(shí)伦仍,主要問題就是:用這種方式實(shí)現(xiàn)下拉刷新,刷新效果的進(jìn)度條肯定在頭布局中痹籍,那么進(jìn)入頁面先刷新呢铆,后加載數(shù)據(jù)的效果就實(shí)現(xiàn)不了,因?yàn)橄人⑿露撞鸵@示頭布局,頭布局顯示的前提就是recycleView數(shù)據(jù)顯示完整悠垛,也就是刷新之前线定,要先加載完整數(shù)據(jù),這簡直是個(gè)悖論H仿颉=锛ァ!湾趾!
備注
- 這部分貼的代碼是關(guān)于整篇文章內(nèi)容的最終代碼芭商,算是一個(gè)demo,代碼不夠嚴(yán)謹(jǐn)(比如進(jìn)度條隱藏展示前后是否手動(dòng)停止或開啟進(jìn)度條更節(jié)省內(nèi)存),重點(diǎn)看實(shí)現(xiàn)思路哈搀缠。
- 關(guān)于recycleView的item點(diǎn)擊事件的實(shí)現(xiàn)思路铛楣,在代碼中也已經(jīng)實(shí)現(xiàn)了,沒有單獨(dú)拎出來而已艺普,需要的同學(xué)可以關(guān)注adaper中接口RecycleViewItemClickCallBack的實(shí)現(xiàn)相關(guān)代碼簸州,或者自行www.baidu.com哈.
總結(jié)
到這里這篇文章基本接近尾聲了,我有點(diǎn)小感觸歧譬,作為Android開發(fā)人員岸浑,看再多的書,不上手敲代碼瑰步,效率很低矢洲,上手敲代碼,才會(huì)想到很多問題缩焦,才能看到很多細(xì)節(jié)東西读虏。所以看書不錯(cuò),但是一定要看著書敲一遍舌界,才能學(xué)到更多東西掘譬。再者,有收獲呻拌,就要寫出來葱轩,寫思路寫收獲的過程,其實(shí)是個(gè)自我梳理的過程,在這個(gè)過程中靴拱,你會(huì)強(qiáng)迫自己梳理垃喊,觸類旁通,會(huì)有更多收獲袜炕!這是我2019第一篇文章本谜,希望自己能夠堅(jiān)持寫文章,至少每個(gè)月一篇文章偎窘。另外勸各位王者召喚師們乌助,少玩游戲吧,特么我今天駕駛本到期換本去陌知,竟然說我色弱(最后給中介200大洋他托,才讓我過了nnd),這在之前就從來都沒有的仆葡,先不說色弱和玩手機(jī)有沒關(guān)系赏参,但是我感覺我視力一天不如一天,少玩手機(jī)沿盅,多看書把篓,終究不會(huì)錯(cuò)的!QА韧掩!