關(guān)于recycleView基礎(chǔ)展示,下拉刷新芭碍,下拉加載徒役,刪除動(dòng)畫,添加頭布局和尾布局.......

去年在大神公眾號評論點(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А韧掩!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市南窗,隨后出現(xiàn)的幾起案子揍很,更是在濱河造成了極大的恐慌,老刑警劉巖万伤,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窒悔,死亡現(xiàn)場離奇詭異,居然都是意外死亡敌买,警方通過查閱死者的電腦和手機(jī)简珠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虹钮,“玉大人聋庵,你說我怎么就攤上這事≤搅唬” “怎么了祭玉?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長春畔。 經(jīng)常有香客問我脱货,道長岛都,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任振峻,我火速辦了婚禮臼疫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扣孟。我一直安慰自己烫堤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布凤价。 她就那樣靜靜地躺著鸽斟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪利诺。 梳的紋絲不亂的頭發(fā)上湾盗,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音立轧,去河邊找鬼。 笑死躏吊,一個(gè)胖子當(dāng)著我的面吹牛氛改,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播比伏,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胜卤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赁项?” 一聲冷哼從身側(cè)響起葛躏,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悠菜,沒想到半個(gè)月后舰攒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悔醋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年摩窃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芬骄。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猾愿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出账阻,到底是詐尸還是另有隱情蒂秘,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布淘太,位于F島的核電站姻僧,受9級特大地震影響规丽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜段化,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一嘁捷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧显熏,春花似錦雄嚣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蕴轨,卻和暖如春港谊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背橙弱。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工歧寺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棘脐。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓斜筐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛀缝。 傳聞我的和親對象是個(gè)殘疾皇子顷链,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容