vlayout 实战之adapter封装

2017-07-05  本文已影响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地址
第一次写,有没有写清楚的,欢迎大家一起讨论~~~

上一篇下一篇

猜你喜欢

热点阅读