vlayout 实战之adapter封装

本文主要讲的是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地址
第一次写,有没有写清楚的,欢迎大家一起讨论~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,799评论 25 707
  • 简介: 提供一个让有限的窗口变成一个大数据集的灵活视图。 术语表: Adapter:RecyclerView的子类...
    酷泡泡阅读 5,148评论 0 16
  • 这篇文章分三个部分,简单跟大家讲一下 RecyclerView 的常用方法与奇葩用法;工作原理与ListView比...
    LucasAdam阅读 4,379评论 0 27
  • 梦幻交响曲(组诗) 谢鹤仁 1)幽灵 沙漠立场不稳 胡杨沉默无语 一种生命要存活 首先是独步,漂泊 寻找一片合适的...
    谢鹤仁阅读 210评论 1 1
  • 以何承生命之轻 只依稀记得很多年以前,我重复着走着我家小镇上的那条水泥街道,下过雨后的路上湿淋淋的,灰蒙蒙的天,...
    苏家有妖孽阅读 177评论 0 0