RecyclerView LayoutManager分析 添加头部尾部

如果图片不能显示 请点击这里

RecyclerView使用也有一段时间了 他的出现是对ListView,GridView的进化,
LayoutManager负责布局
Adpater负责数据处理

自带缓存机制,不用开发者过多处理,更多的关注业务逻辑就行

更加灵活,但是需要开发者多多的操作相关事件,比如点击事件那就需要自定义接口,没有类似于ListView的addHaedView等方法

在使用中用的多的就是有添加头部尾部 加载更多 下拉刷新(可以和系统的refreshlayout)一起使用

项目中我用的是easyRecyclerView 开源项目(自行github 挺好用,功能挺全 )

正题来了
前面看到一篇博客 分析如何用LayoutManager布局管理来实现头部尾部的添加 比较方便
源地址
http://m.blog.csdn.net/blog/oushangfeng123/47435867

讲用LayoutManager来实现RecycleView的头部尾部添加,特意实现了一遍 它里面稍微分析了一下 看了一下源码 我就不分析了 看他的原帖去吧

先看个效果 都是添加了头部和尾部

这里写图片描述

主Activity代码

 public class RecyclerViewMainActivity extends ActionBarActivity {

    private android.widget.Button bt1;
    private android.widget.Button bt2;
    private android.widget.Button bt3;
    private RecyclerView rcv;
    private GridLayoutManager gridLayoutManager;
    private StaggeredGridLayoutManager staggeredGridLayoutManager;
    List<String> lists=new ArrayList<String>();
    private LinearLayoutManager linearLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view_main);
        this.rcv = (RecyclerView) findViewById(R.id.rcv);

        this.bt3 = (Button) findViewById(R.id.bt3);
        this.bt2 = (Button) findViewById(R.id.bt2);
        this.bt1 = (Button) findViewById(R.id.bt1);

        bt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                gridLayoutManager = new GridLayoutManager(RecyclerViewMainActivity.this, 2);
                lists.clear();
                for(int i=0 ; i<20 ; i++){
                    lists.add("123"+i);
                }
                RecycleViewGridAdapter recycleViewAdapter = new RecycleViewGridAdapter(lists);
                LayoutInflater layoutInflater = getLayoutInflater();
                View view = layoutInflater.inflate(R.layout.item_top, null);
                recycleViewAdapter.addHeadView(view);
                View view1 = layoutInflater.inflate(R.layout.item_foot, null);
                recycleViewAdapter.addFootView(view1);

                //如果添加了头部或者尾部 就需要做相关的SpanSize的修改 回调接口 设置layoutmanager的spanSize
                recycleViewAdapter.setChangeGridLayoutManager(new RecycleViewGridAdapter.ChangeGridLayoutManagerSpance() {
                    @Override
                    public void change(final int size, final boolean isAddHead, final boolean isAddFoot) {
                        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                            @Override
                            public int getSpanSize(int position) {
                                int spanSzie = 1;
                                if (isAddHead) {
                                    if (position == 0) {
                                        spanSzie = gridLayoutManager.getSpanCount();
                                    }
                                }

                                if (isAddFoot) {
                                    if (position == size) {
                                        spanSzie = gridLayoutManager.getSpanCount();
                                    }
                                }
                                return spanSzie;
                            }
                        });
                    }
                });
                rcv.setLayoutManager(gridLayoutManager);
                rcv.setAdapter(recycleViewAdapter);
            }
        });


        bt3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                staggeredGridLayoutManager=new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
                lists.clear();
                for(int i=0 ; i<20 ; i++){
                    lists.add("123"+i);
                }
                RecycleViewStageredAdapter recycleViewStageredAdapter = new RecycleViewStageredAdapter(lists);
                recycleViewStageredAdapter.addHeadView(R.layout.item_top);
                recycleViewStageredAdapter.addFootView(R.layout.item_top);

                rcv.setLayoutManager(staggeredGridLayoutManager);
                rcv.setAdapter(recycleViewStageredAdapter);
            }
        });

        bt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                 linearLayoutManager=new LinearLayoutManager(RecyclerViewMainActivity.this);
                linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);

                lists.clear();
                for(int i=0 ; i<20 ; i++){
                    lists.add("123"+i);
                }
                RecycleviewLinearAdapter recycleviewLinearAdapter=new RecycleviewLinearAdapter(lists);

                LayoutInflater layoutInflater = getLayoutInflater();
                View view = layoutInflater.inflate(R.layout.item_top, null);
                recycleviewLinearAdapter.addHeadView(view);
                View view1 = layoutInflater.inflate(R.layout.item_foot, null);
                recycleviewLinearAdapter.addFootView(view1);

                rcv.setLayoutManager(linearLayoutManager);
                rcv.setAdapter(recycleviewLinearAdapter);

            }
        });
    }
    }    

然后是各个ViewHolder 整体结构图
Paste_Image.png

RecycleviewLinearAdapter 代码

    public class RecycleviewLinearAdapter<T> extends RecyclerView.Adapter<LinearViewHolder> {
    private static final int TYPE_HEADER = 0, TYPE_ITEM = 1, TYPE_FOOT = 2;
    public List<T> mDatas;
    private View headView;
    private View footView;
    private int headViewSize = 0;
    private int footViewSize = 0;
    private boolean isAddFoot = false;
    private boolean isAddHead = false;

    public RecycleviewLinearAdapter(List<T> mDatas) {
        this.mDatas = mDatas;
    }

    public void addHeadView(View view) {
        headView = view;
        headViewSize = 1;
        isAddHead = true;
    }

    public void addFootView(View view) {
        footView = view;
        footViewSize = 1;
        isAddFoot = true;
    }

    @Override
    public int getItemViewType(int position) {
        int type = TYPE_ITEM;
        if (headViewSize == 1 && position == 0) {
            type = TYPE_HEADER;
        } else if (footViewSize == 1 && position == getItemCount() - 1) {
            //最后一个位置
            type = TYPE_FOOT;
        }
        return type;
    }


    @Override
    public LinearViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = null;
        switch (viewType) {
            case TYPE_HEADER:
                view = headView;
                break;

            case TYPE_ITEM:
                view = View.inflate(parent.getContext(), R.layout.item_icon, null);
                break;

            case TYPE_FOOT:
                view = footView;
                break;
        }
        return new LinearViewHolder(view);
    }

    @Override
    public void onBindViewHolder(LinearViewHolder holder, int position) {
    }

    @Override
    public int getItemCount() {
        return mDatas.size()+headViewSize+footViewSize;
    }
    }

    class LinearViewHolder extends RecyclerView.ViewHolder {
    public LinearViewHolder(View itemView) {
        super(itemView);
    }
    }

RecycleViewGridAdapter 代码

    public class RecycleViewGridAdapter<T> extends RecyclerView.Adapter<MyViewHolder> {
    private static final int TYPE_HEADER = 0, TYPE_ITEM = 1, TYPE_FOOT = 2;

    public List<T> mDatas;
    private View headView;
    private View footView;
    private int headViewSize = 0;
    private int footViewSize = 0;
    private ChangeGridLayoutManagerSpance changeGridLayoutManager;
    private boolean isAddFoot=false;
    private boolean isAddHead=false;




    public interface ChangeGridLayoutManagerSpance{
        public void change(int size, boolean isAddHead, boolean isAddFoot);
    }
    //提供接口给 让LayoutManager根据添加尾部 头部与否来做判断 显示头部与底部的SpanSize要在添加头部和尾部之后 
    public void setChangeGridLayoutManager(ChangeGridLayoutManagerSpance changeGridLayoutManager){
        this.changeGridLayoutManager=changeGridLayoutManager;
        changeGridLayoutManager.change(getItemCount()-1,isAddHead,isAddFoot);
    }

    public RecycleViewGridAdapter(List<T> datas) {
        mDatas = datas;
    }

    public void addHeadView(View view) {
        headView = view;
        headViewSize = 1;
        isAddHead=true;
    }

    public void addFootView(View view) {
        footView = view;
        footViewSize = 1;
        isAddFoot=true;
    }

    @Override
    public int getItemViewType(int position) {
        int type = TYPE_ITEM;

        if (headViewSize==1 && position == 0) {
            type = TYPE_HEADER;
        } else if (footViewSize==1 && position == getItemCount()-1) {
            //最后一个位置
            type = TYPE_FOOT;
        }
        return type;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = null;
        switch (i) {
            case TYPE_HEADER:
                view = headView;
                break;

            case TYPE_ITEM:
                view = View.inflate(viewGroup.getContext(), R.layout.item_icon, null);
                break;

            case TYPE_FOOT:
                view =footView;
                break;
        }
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

    }
    @Override
    public int getItemCount() {
        return mDatas.size() + headViewSize + footViewSize;
    }
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
    public MyViewHolder(View itemView) {
        super(itemView);
    }
    }

RecycleViewStageredAdapter 代码

 public class RecycleViewStageredAdapter<T> extends RecyclerView.Adapter<MyViewHolder1>{
    private static final int TYPE_HEADER = 0, TYPE_ITEM = 1, TYPE_FOOT = 2;

    public List<T> mDatas;
    private int headViewid;
    private int headViewSize;
    private boolean isAddHead;
    private int footViewid;
    private int footViewSize;
    private boolean isAddFoot;

    public RecycleViewStageredAdapter(List<T> mDatas) {
        this.mDatas = mDatas;
    }

    public void addHeadView(int view) {
        headViewid = view;
        headViewSize = 1;
        isAddHead=true;
    }

    public void addFootView(int view) {
        footViewid = view;
        footViewSize = 1;
        isAddFoot=true;
    }

    @Override
    public MyViewHolder1 onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = null;
        switch (i) {
            case TYPE_HEADER:
                view = LayoutInflater.from(viewGroup.getContext()).inflate(headViewid, viewGroup, false);
                break;

            case TYPE_ITEM:
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_icon, viewGroup, false);
                break;

            case TYPE_FOOT:
                view = LayoutInflater.from(viewGroup.getContext()).inflate(footViewid, viewGroup, false);
                break;
        }
        return new MyViewHolder1(view);
    }

    @Override
    public void onBindViewHolder(MyViewHolder1 myViewHolder, int i) {
        switch (myViewHolder.getItemViewType()) {
            case TYPE_HEADER:

                // 获取cardview的布局属性,记住这里要是布局的最外层的控件的布局属性,如果是里层的会报cast错误
                StaggeredGridLayoutManager.LayoutParams clp = (StaggeredGridLayoutManager.LayoutParams) myViewHolder.cardview.getLayoutParams();
                // 最最关键一步,设置当前view占满列数,这样就可以占据两列实现头部了
                if(clp!=null)
                    clp.setFullSpan(true);
                break;

            case TYPE_ITEM:
                ViewGroup.LayoutParams layoutParams=myViewHolder.cardview.getLayoutParams();
                layoutParams.height= (int) ((i%mDatas.size()+1)*20);
                myViewHolder.cardview.setLayoutParams(layoutParams);
                break;

            case TYPE_FOOT:
                // 获取cardview的布局属性,记住这里要是布局的最外层的控件的布局属性,如果是里层的会报cast错误
                StaggeredGridLayoutManager.LayoutParams clp1 = (StaggeredGridLayoutManager.LayoutParams) myViewHolder.cardview.getLayoutParams();
                // 最最关键一步,设置当前view占满列数,这样就可以占据两列实现头部了
                clp1.setFullSpan(true);

                break;
        }
    }

    @Override
    public int getItemViewType(int position) {

        int type = TYPE_ITEM;
        if (headViewSize==1 && position == 0) {
            type = TYPE_HEADER;
        } else if (footViewSize==1 && position == getItemCount()-1) {
            //最后一个位置
            type = TYPE_FOOT;
        }
        return type;
    }

    @Override
    public int getItemCount() {
        return mDatas.size()+headViewSize+footViewSize;
    }
    }

    class MyViewHolder1 extends RecyclerView.ViewHolder{
    public CardView cardview;
    public MyViewHolder1(View itemView) {
        super(itemView);
        cardview = (CardView) itemView.findViewById(R.id.cv);
    }
    }

发现其实都很长不差不多太多 LinearLayoutManager没啥难点
GridLayoutManager 是要设置SpanSize每行的占位大小

StaggerLayoutManager 就是要获取StaggerLayoutManager的LayoutParams 的setFullSpan 方法来设置占位宽度

贴一贴布局代码

item

  <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/cv"
    >
    <ImageView
        android:id="@+id/iv_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"
        />
    </android.support.v7.widget.CardView >

top

 <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/cv"
    xmlns:app="http://schemas.android.com/apk/res-auto"

    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:cardCornerRadius="8dp"
    app:cardElevation="5dp"
    app:contentPadding="1dp"

    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="top"
        android:textSize="100dp" />
    </android.support.v7.widget.CardView>

foot

 <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/cv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Foot"
        android:textSize="100dp" />
    </android.support.v7.widget.CardView>
RecyclerView是Android平台上用于高效展示大量数据集的一个组件,它可以灵活地展示多种不同类型的列表项。要在RecyclerView添加头部尾部布局,你通常需要使用`RecyclerView.LayoutManager`,并且可以通过添加`RecyclerView.Adapter`的子类来实现。 以下是添加头部尾部布局的一种常见方法: 1. **定义头部尾部布局的XML文件**:首先,你需要创建两个XML布局文件,分别表示头部尾部的布局。 2. **修改Adapter**:在你的`RecyclerView.Adapter`子类中,你需要处理数据集的改变以包含头部尾部。通常,你会在`getItemCount()`方法中返回数据集的数量加上头部尾部的数量。同时,根据位置不同,在`onCreateViewHolder()`和`onBindViewHolder()`方法中提供不同的视图类型。 3. **在ViewHolder中区分视图类型**:在`onCreateViewHolder()`中,通过不同的viewType参数创建头部尾部和数据项的ViewHolder。在`onBindViewHolder()`中,根据viewType绑定相应的数据到ViewHolder上。 4. **管理头部尾部添加**:在适配器的某个方法中(比如`onAttachedToRecyclerView`),将头部尾部的视图添加RecyclerView中。这通常通过在适配器中持有头部尾部的视图引用,并在`onCreateViewHolder()`中创建这些视图来完成。 5. **将头部尾部视图添加RecyclerView**:可以在`RecyclerView`的适配器中直接将头部尾部视图添加到数据集合的开始和结束,或者使用`addHeaderView`和`addFooterView`方法,如果这些方法被`RecyclerView`的布局管理器(如`LinearLayoutManager`)支持的话。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值