美文网首页
vlayout 实战之adapter封装

vlayout 实战之adapter封装

作者: 我弟是个程序员 | 来源:发表于2017-07-05 17:15 被阅读0次

    本文主要讲的是vlayout使用过程中,对适配器DelegateAdapter的封装。实现了的效果,相当于传统的Viewpager + 自由布局(此处还可以其他实现方式如GridView等) + ListView

    先看看阿里巴巴的设计思路:
    通过定制化的LayoutManager,接管整个RecyclerView的布局逻辑;LayoutManager管理了一系列LayoutHelper,LayoutHelper负责具体布局逻辑实现的地方;每一个LayoutHelper负责页面某一个范围内的组件布局;不同的LayoutHelper可以做不同的布局逻辑,因此可以在一个RecyclerView页面里提供异构的布局结构,这就能比系统自带的LinearLayoutManager、GridLayoutManager等提供更加丰富的能力。同时支持扩展LayoutHelper来提供更多的布局能力。

    解析上面一段话就是:**RecyclerView + VirtualLayoutManager + DelegateAdapter **来实现各种布局,下面上一个本人的demo效果图如下:



    你没有看错,上面的视图,就是有一个跟元素RecyclerView得来的。

    话不多说,下面来分析,首先导入依赖(Module:app):

      compile ('com.alibaba.android:vlayout:1.0.9@aar') {
            transitive = true
        }
    

    跟布局不用解释,一个简单的RecyclerView:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/main_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#fff"
            android:clipToPadding="true"
            android:paddingLeft="0dp"
            android:paddingRight="0dp"
            android:requiresFadingEdge="none"
            android:scrollbars="vertical"/>
    
    </FrameLayout>
    

    下面看MainActivity.java

    import android.graphics.Rect;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.alibaba.android.vlayout.DelegateAdapter;
    import com.alibaba.android.vlayout.VirtualLayoutManager;
    import com.alibaba.android.vlayout.layout.GridLayoutHelper;
    import com.alibaba.android.vlayout.layout.LinearLayoutHelper;
    import com.dingfang.org.testvlayout.adapter.BannerAdapter;
    import com.dingfang.org.testvlayout.adapter.ClassficationAdapter;
    import com.dingfang.org.testvlayout.adapter.ListAdapter;
    import com.dingfang.org.testvlayout.util.RequestData;
    
    import java.util.LinkedList;
    import java.util.List;
    
    
    public class MainActivity extends AppCompatActivity {
    
        private RecyclerView recyclerView; //跟布局
        private VirtualLayoutManager layoutManager; //管理工具
        private DelegateAdapter delegateAdapter;    //适配器代理
        private List<DelegateAdapter.Adapter> adapters; //具体布局的适配器集合
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initView();
            initWedgitAdapter();
            doCombine();
        }
    
    
        /**
         * 初始化视图
         */
        private void initView() {
            recyclerView = (RecyclerView) findViewById(R.id.main_view);
    
            /**
             * 签订管理协议
             */
            layoutManager = new VirtualLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);
    
            /**
             * 设置适配器
             */
            delegateAdapter = new DelegateAdapter(layoutManager, true);//true or false 表示不同类型的adpter,item是否会复用
            recyclerView.setAdapter(delegateAdapter);
    
            /**
             * 具体布局的适配器 集合
             */
            adapters = new LinkedList<>();
        }
    
        /**
         * 初始化具体的布局
         */
        private void initWedgitAdapter() {
            //banner,可以滑动的广告栏,就是图中最上面部分
            adapters.add(new BannerAdapter(this, new LinearLayoutHelper(), new VirtualLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 300), RequestData.getImageViewsForBanner(this)));
    
            //图中中间布局部分
            GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(4);//列,
            gridLayoutHelper.setVGap(4); // 垂直的间距
    //        gridLayoutHelper.setWeights(new float[]{20.0f,30.0f,30.0f,20.0f}); //设置比例
            adapters.add(new ClassficationAdapter(this, gridLayoutHelper, RequestData.getLabels()));
    
            //图中下面列表
            LinearLayoutHelper layoutHelper1 = new LinearLayoutHelper();
    //        layoutHelper1.setAspectRatio(1.0f);// width / height,即宽高比
            layoutHelper1.setDividerHeight(10);
            adapters.add(new ListAdapter(this, layoutHelper1, RequestData.getListItems()));
    
        }
    
        /**
         * 最后的一步
         */
        private void doCombine() {
            delegateAdapter.setAdapters(adapters);
        }
    }
    
    

    上面代码部分除了RequestData.getImageViewsForBanner(this)、RequestData.getLabels()、RequestData.getListItems()是我构造的假数据,为了不想脏了组件Activity。其余的,代码中已经注释很清楚了,不明白的可以留言哦~~~

    其实上面代码不是今天要讲到的只要部分,下面才是重点,上面MainActivity.java中,在这段代码中

      private void initWedgitAdapter() {
            //banner,可以滑动的广告栏,就是图中最上面部分
            adapters.add(new BannerAdapter(this, new LinearLayoutHelper(), new VirtualLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 300), RequestData.getImageViewsForBanner(this)));
    
            //图中中间布局部分
            GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(4);//列,
            gridLayoutHelper.setVGap(4); // 垂直的间距
    //        gridLayoutHelper.setWeights(new float[]{20.0f,30.0f,30.0f,20.0f}); //设置比例
            adapters.add(new ClassficationAdapter(this, gridLayoutHelper, RequestData.getLabels()));
    
            //图中下面列表
            LinearLayoutHelper layoutHelper1 = new LinearLayoutHelper();
    //        layoutHelper1.setAspectRatio(1.0f);// width / height,即宽高比
            layoutHelper1.setDividerHeight(10);
            adapters.add(new ListAdapter(this, layoutHelper1, RequestData.getListItems()));
    
        }
    

    明显有几个Adapter,如BannerAdapter、ClassficationAdapter和ListAdapter,由于篇幅原因,下面先看其中一个ClassficationAdapter吧。

    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import com.alibaba.android.vlayout.LayoutHelper;
    import com.alibaba.android.vlayout.VirtualLayoutManager;
    import com.dingfang.org.testvlayout.R;
    import com.dingfang.org.testvlayout.adapter.base.BaseDelegateAdapter;
    import com.dingfang.org.testvlayout.adapter.base.BaseViewHolder;
    import com.dingfang.org.testvlayout.entity.LabelEntity;
    
    import java.util.List;
    
    /**
     * 宫格数据的适配器
     */
    
    public class ClassficationAdapter  extends BaseDelegateAdapter<ClassficationAdapter.ClassficationViewHolder> {
    
        List<LabelEntity> labelEntities;
    
        public ClassficationAdapter() {
        }
    
        public ClassficationAdapter(Context mContext, LayoutHelper mLayoutHelper, List<LabelEntity> labelEntities) {
            this(mContext, mLayoutHelper, null, labelEntities);
        }
    
        public ClassficationAdapter(Context mContext, LayoutHelper mLayoutHelper, VirtualLayoutManager.LayoutParams mLayoutParams, List<LabelEntity> labelEntities) {
            super(mContext, mLayoutHelper, mLayoutParams);
            this.labelEntities = labelEntities;
        }
    
        @Override
        public ClassficationViewHolder doOnCreateViewHolder(ViewGroup parent, int viewType) {
            return new ClassficationViewHolder(LayoutInflater.from(this.getContext()).inflate(R.layout.label_item,parent,false));
        }
    
        @Override
        public void doOnBindViewHolder(ClassficationViewHolder holder, int position) {
            if (holder instanceof ClassficationViewHolder) {
                LabelEntity item = labelEntities.get(position);
                holder.imageView.setImageResource(item.getLabelImage());
                holder.textView.setText(item.getLabelText());
            }
        }
    
        @Override
        public int doGetItemCount() {
            return labelEntities == null ? 0 : labelEntities.size();
        }
    
        static class ClassficationViewHolder extends BaseViewHolder {
            public ImageView imageView;
            public TextView textView;
    
            public ClassficationViewHolder(View itemView) {
                super(itemView);
                imageView = (ImageView) itemView.findViewById(R.id.iv_label);
                textView = (TextView) itemView.findViewById(R.id.tv_label);
            }
        }
    }
    
    

    此适配器,是中间那个8个宫格数据的适配器,咦,它怎么继承了BaseDelegateAdapter,并且ClassficationAdapter.ClassficationViewHolder也继承了BaseViewHolder ,下面就来看看这两个抽象类吧。

    BaseDelegateAdapter.java ,本篇文章最值得看的部分

    import android.content.Context;
    import android.view.ViewGroup;
    
    import com.alibaba.android.vlayout.DelegateAdapter;
    import com.alibaba.android.vlayout.LayoutHelper;
    import com.alibaba.android.vlayout.VirtualLayoutManager;
    
    /**
     * 适配器抽象类
     */
    
    public abstract class BaseDelegateAdapter <T extends BaseViewHolder> extends DelegateAdapter.Adapter<T>  {
    
        /**
         * 上下文环境
         * 提供get方法来获取
         */
        private Context mContext;
    
        /**
         * 必要的布局管理属性
         * 被框架管理,所以写在抽象类里面
         */
        private LayoutHelper mLayoutHelper;
    
        /**
         * itemView布局中 跟布局的布局参数
         * 因为每一个实体类都要做此操作,所以也放在抽象类里面
         */
        private VirtualLayoutManager.LayoutParams mLayoutParams;
    
        public BaseDelegateAdapter() {
    
        }
    
        public BaseDelegateAdapter(Context mContext, LayoutHelper mLayoutHelper) {
            this(mContext,mLayoutHelper,null);
        }
    
        public BaseDelegateAdapter(Context mContext, LayoutHelper mLayoutHelper, VirtualLayoutManager.LayoutParams mLayoutParams) {
            this.mContext = mContext;
            this.mLayoutHelper = mLayoutHelper;
            this.mLayoutParams = mLayoutParams;
        }
    
        public Context getContext() {
            return mContext;
        }
    
        @Override
        public LayoutHelper onCreateLayoutHelper() {
            return this.mLayoutHelper;
        }
    
        @Override
        public T onCreateViewHolder(ViewGroup parent, int viewType) {
            return doOnCreateViewHolder(parent,viewType);
        }
    
        @Override
        public void onBindViewHolder(T holder, int position) {
            if (this.mLayoutParams != null) {
                holder.getView().setLayoutParams(this.mLayoutParams);//设置跟布局相关属性
            }
            doOnBindViewHolder(holder, position);
        }
    
        @Override
        public int getItemCount() {
            return doGetItemCount();
        }
    
        //子类需要实现
        public abstract T doOnCreateViewHolder(ViewGroup parent, int viewType);
        public abstract void doOnBindViewHolder(T holder, int position);
        public abstract int doGetItemCount();
    }
    

    代码浅显易懂,不必多bb了,这里讲阿里巴巴提供的DelegateAdapter,进行了封装,这是本文的重点,可以细细评味下,不明白的可以评论哦~~~

    BaseViewHolder.java ,这个就简单了

    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * 通用的ViewHolider
     */
    
    public abstract class BaseViewHolder extends RecyclerView.ViewHolder{
        private View itemView;
    
        public BaseViewHolder(View itemView) {
            super(itemView);
            this.itemView = itemView;
        }
        public View getView() {
            return this.itemView;
        }
    }
    
    

    好了代码就贴这么多了,本文主要是提供一种思路和规范,通过BaseViewHolder,BaseDelegateAdapter这两个抽象类来实现,使得继承其的类不得不遵循相关的协议。

    下面贴出demo地址
    第一次写,有没有写清楚的,欢迎大家一起讨论~~~

    相关文章

      网友评论

          本文标题:vlayout 实战之adapter封装

          本文链接:https://www.haomeiwen.com/subject/vdpqhxtx.html