阿里VLayout学习笔记(Kotlin)

文章目录

  • 阿里VLayout学习笔记(Kotlin)
    • VLayout中LayoutHelper分类(辅助Adapter实现RecyclerView的Item各种类型的布局方式)
    • 第一步:设置依赖
    • 第二步: 为RecyclerView设置回收复用池大小
    • 第二步: 初始化RecyclerView
    • 最后一步添加忽略
    • VLayout工具类
    • 参考

VLayout中LayoutHelper分类(辅助Adapter实现RecyclerView的Item各种类型的布局方式)

LinearLayoutHelper: 线性布局
GridLayoutHelper: Grid布局, 支持横向的colspan
FixLayoutHelper: 固定布局,始终在屏幕固定位置显示
ScrollFixLayoutHelper: 固定布局,但之后当页面滑动到该图片区域才显示, 可以用来做返回顶部或其他书签等
FloatLayoutHelper: 浮动布局,可以固定显示在屏幕上,但用户可以拖拽其位置
ColumnLayoutHelper: 栏格布局,都布局在一排,可以配置不同列之间的宽度比值
SingleLayoutHelper: 通栏布局,只会显示一个组件View
OnePlusNLayoutHelper: 一拖N布局,可以配置1-5个子元素
StickyLayoutHelper: stikcy布局, 可以配置吸顶或者吸底
StaggeredGridLayoutHelper: 瀑布流布局,可配置间隔高度/宽度
新建Helper的方法详见VLayout

第一步:设置依赖

在项目app->build.gradle->dependencies中添加如下依赖
注意:使用过程中可能存在AnimatorCompatHelper.java找不到的情况,原因可能是当前编译使用的support-v4包中不存在该类(例如26.0.1)
解决方案一:在项目中新建android.support.v4.animation包,并将…\sdk\sources\android-25\android\support\v4\animation路径(在SDK安装路径下搜索AnimatorCompatHelper.java得到的路径)下的AnimatorCompatHelper.java复制到新建的包中
解决方案二:使用com.android.support:recyclerview-v7和com.android.support:support-v4最新的依赖包

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

第二步: 为RecyclerView设置回收复用池大小

如果一屏内相同类型的 ItemView 个数比较多,需要设置一个合适的大小,防止来回滚动时重新创建 ItemView

        val viewPool = RecyclerView.RecycledViewPool()rv.setRecycledViewPool(viewPool)//参数一:itemView类型ID  参数二:最大回收复用ItemView数(设置1:全部重建,设置10:屏幕最多保留10个相同ItemView不重建)viewPool.setMaxRecycledViews(0, 10)

第二步: 初始化RecyclerView

方法一:通过DelegateAdapter初始化RecyclerView

        //参数一:上下文   参数二:布局方向val layoutManager = VirtualLayoutManager(mContext, VirtualLayoutManager.VERTICAL)rv.setLayoutManager(layoutManager)//参数一:布局管理器  参数二:是否所有子adapter共享Item布局(当hasConsistItemType=true的时候,不论是不是属于同一个子adapter,相同类型的item都能复用。表示它们共享一个类型。 当hasConsistItemType=false的时候,不同子adapter之间的类型不共享)val delegateAdapter = DelegateAdapter(layoutManager, true)val adapters = ArrayList<DelegateAdapter.Adapter<RecyclerView.ViewHolder>>//MyAdapter是继承DelegateAdapter.Adapter的实例适配器,详见BaseVLayoutDelegateAdapteradapters.add(MyAdapter(floatLayoutHelper))...adapters.add(MyAdapter(stickyLayoutHelper))//设置子adapter集合delegateAdapter.setAdapters(adapters)//为RecyclerView设置adapterrv.adapter = delegateAdapter

方法二:通过VirtualLayoutAdapter初始化RecyclerView

 //参数一:上下文   参数二:布局方向
val layoutManager = VirtualLayoutManager(mContext, VirtualLayoutManager.VERTICAL) rv.setLayoutManager(layoutManager)
val helpers = LinkedList<LayoutHelper>()
helpers.add(stickyLayoutHelper)
...
helpers.add(linearLayoutHelper)
//Adapter是继承VirtualLayoutAdapter的实例适配器 详见 BaseVLayoutVirtualLayoutAdapter
val adapter = Adapter(layoutManager, helpers)
rv.adapter = adapter

最后一步添加忽略

-keepattributes InnerClasses
-keep class com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx { *; }
-keep class android.support.v7.widget.RecyclerView$LayoutParams { *; }
-keep class android.support.v7.widget.RecyclerView$ViewHolder { *; }
-keep class android.support.v7.widget.ChildHelper { *; }
-keep class android.support.v7.widget.ChildHelper$Bucket { *; }
-keep class android.support.v7.widget.RecyclerView$LayoutManager { *; }

VLayout工具类

object VLayoutHelper {fun initRecyclerView(rv: RecyclerView,@OrientationMode orientation: Int,hasConsistItemType: Boolean,adapters: List<DelegateAdapter.Adapter<RecyclerView.ViewHolder>>) {val layoutManager = VirtualLayoutManager(MyAPP.getInstance(), orientation)rv.setLayoutManager(layoutManager)val delegateAdapter = DelegateAdapter(layoutManager, hasConsistItemType)delegateAdapter.setAdapters(adapters as List<DelegateAdapter.Adapter<RecyclerView.ViewHolder>>?)rv.adapter = delegateAdapter}fun initRecyclerView(rv: RecyclerView, @OrientationMode orientation: Int, hasConsistItemType: Boolean, adapter: VirtualLayoutAdapter<RecyclerView.ViewHolder>) {val layoutManager = VirtualLayoutManager(MyAPP.getInstance(), orientation)rv.setLayoutManager(layoutManager)rv.adapter = adapter}fun setViewPool(rv: RecyclerView, viewType: Int, max: Int) {val viewPool = RecyclerView.RecycledViewPool()rv.setRecycledViewPool(viewPool)viewPool.setMaxRecycledViews(viewType, max)}/*** 获取线性布局Helper*/fun getLinearLayoutHelper(count: Int, dividerHeight: Int): LinearLayoutHelper {val linearLayoutHelper = LinearLayoutHelper()//线性布局的Item条目数linearLayoutHelper.itemCount = countlinearLayoutHelper.setDividerHeight(dividerHeight)return linearLayoutHelper}fun getLinearLayoutHelper(@DimenRes dividerHeightID: Int): LinearLayoutHelper {return getLinearLayoutHelper(0, Resources.getSystem().getDimensionPixelOffset(dividerHeightID))}/*** 获取网格布局*/fun getGridLayoutHelper(spanCount: Int, isAutoExpand: Boolean): GridLayoutHelper {return getGridLayoutHelper(spanCount, isAutoExpand, 0, null, null)}fun getGridLayoutHelper(spanCount: Int, position: ((Int) -> Int)?): GridLayoutHelper {return getGridLayoutHelper(spanCount, false, 0, null, position)}fun getGridLayoutHelper(spanCount: Int, itemCount: Int, position: ((Int) -> Int)?): GridLayoutHelper {return VLayoutHelper.getGridLayoutHelper(spanCount, false, itemCount, null, 0, 0, position)}fun getGridLayoutHelper(spanCount: Int, isAutoExpand: Boolean, itemCount: Int, weights: FloatArray?,position: ((Int) -> Int)?): GridLayoutHelper {return VLayoutHelper.getGridLayoutHelper(spanCount, isAutoExpand, itemCount, weights, 0, 0, position)}fun getGridLayoutHelper(spanCount: Int, isAutoExpand: Boolean, itemCount: Int, weights: FloatArray?, gap: Int,position: ((Int) -> Int)?): GridLayoutHelper {return VLayoutHelper.getGridLayoutHelper(spanCount, isAutoExpand, itemCount, weights, gap, gap, position)}fun getGridLayoutHelper(spanCount: Int, isAutoExpand: Boolean, itemCount: Int, weights: FloatArray?,vGap: Int, hGap: Int, position: ((Int) -> Int)?): GridLayoutHelper {var spanSL: GridLayoutHelper.SpanSizeLookup? = nullif (null != position) {spanSL = object : GridLayoutHelper.SpanSizeLookup() {override fun getSpanSize(position: Int): Int {return position(position)}}}//网格布局列数val gridLayoutHelper = GridLayoutHelper(spanCount)//是否自动补全布局(当其设置为true时,如果一行的Item总占用列数小于网格列数,那么Item两头的间距将均匀拉伸使之填满一行)gridLayoutHelper.setAutoExpand(isAutoExpand)//网格布局的Item条目数gridLayoutHelper.itemCount = itemCount//设置每列的权重(表示每列占一行的多大宽度,最大100f,weights的size不能大于网格列数,其值得和不能大于100f)gridLayoutHelper.setWeights(weights)//设置Item的水平间距gridLayoutHelper.hGap = hGap//设置Item的垂直间距gridLayoutHelper.vGap = vGap//指定条目占用一行的指定列数的规则(指定占用列数不能大于网格的列数)gridLayoutHelper.setSpanSizeLookup(spanSL)return gridLayoutHelper}const val TOP_LEFT = 0  //以RecyclerView内左上角为原点const val TOP_RIGHT = 1  //以RecyclerView内右上角为原点const val BOTTOM_LEFT = 2  //以RecyclerView内左下角为原点const val BOTTOM_RIGHT = 3  //以RecyclerView内右下角为原点/*** 以RecyclerView控件内部为基准*/@IntDef(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT)@Retention(AnnotationRetention.SOURCE)private annotation class LayoutHelperAlignType/*** 获取FixLayout固定布局*/fun getFixLayoutHelper(@LayoutHelperAlignType alignType: Int): FixLayoutHelper {return getFixLayoutHelper(alignType, 0, 0)}fun getFixLayoutHelper(@LayoutHelperAlignType alignType: Int, offsetX: Int, offsetY: Int): FixLayoutHelper {//参数一:设置对齐方式(原点位置)  参数二:相对原点X轴偏移量  参数三:相对原点Y轴偏移量val fixLayoutHelper = FixLayoutHelper(alignType,offsetX, offsetY)fixLayoutHelper.itemCount = 1return fixLayoutHelper}const val SHOW_ALWAYS = 0const val SHOW_ON_ENTER = 1const val SHOW_ON_LEAVE = 2@IntDef(SHOW_ALWAYS, SHOW_ON_ENTER, SHOW_ON_LEAVE)@Retention(AnnotationRetention.SOURCE)private annotation class ScrollFixLayoutHelperShowType/*** 这个也是固定布局,而且使继承自FixLayoutHelper的,这个Helper存在一定bug,有可能设置showType无效*- SHOW_ALWAYS:与FixLayoutHelper的行为一致,固定在某个位置;*- SHOW_ON_ENTER:默认不显示视图,当页面滚动到这个视图的位置的时候,才显示;*- SHOW_ON_LEAVE:默认不显示视图,当页面滚出这个视图的位置的时候显示;*/fun getScrollFixLayoutHelper(@LayoutHelperAlignType alignType: Int, @ScrollFixLayoutHelperShowType showType: Int): ScrollFixLayoutHelper {return getScrollFixLayoutHelper(alignType, showType, 0, 0)}fun getScrollFixLayoutHelper(@LayoutHelperAlignType alignType: Int, @ScrollFixLayoutHelperShowType showType: Int, offsetX: Int, offsetY: Int): ScrollFixLayoutHelper {val scrollFixLayoutHelper = ScrollFixLayoutHelper(alignType, offsetX, offsetY)scrollFixLayoutHelper.setShowType(showType)scrollFixLayoutHelper.itemCount = 1return scrollFixLayoutHelper}/*** 获取可拖动布局* 设置dragEnable = true可拖动时* 当其为adapter的第一个helper时可以直接拖动* 否则需要其上一个helper显示后才可以拖动*/fun getFloatLayoutHelper(@LayoutHelperAlignType alignType: Int,dragEnable: Boolean): FloatLayoutHelper {return getFloatLayoutHelper(TOP_LEFT,0,0,dragEnable)}fun getFloatLayoutHelper(posX: Int, posY: Int, dragEnable: Boolean): FloatLayoutHelper {return getFloatLayoutHelper(TOP_LEFT,posX,posY,dragEnable)}fun getFloatLayoutHelper(@LayoutHelperAlignType alignType: Int,posX: Int, posY: Int, dragEnable: Boolean): FloatLayoutHelper {val floatLayoutHelper = FloatLayoutHelper()floatLayoutHelper.setAlignType(alignType)//参数一:相对原点X轴偏移量  参数二:相对原点Y轴偏移量floatLayoutHelper.setDefaultLocation(posX, posY)floatLayoutHelper.setDragEnable(dragEnable)floatLayoutHelper.itemCount = 1return floatLayoutHelper}/*** 获取栏格布局* 只有一行,可通过itemCount设置多列*/fun getColumnLayoutHelper(count: Int, weights: FloatArray?): ColumnLayoutHelper {val columnLayoutHelper = ColumnLayoutHelper()columnLayoutHelper.setWeights(weights)columnLayoutHelper.itemCount = countreturn columnLayoutHelper}/*** 获取通栏布局* 只有一个Item*/fun getSingleLayoutHelper(): SingleLayoutHelper {val singleLayoutHelper = SingleLayoutHelper()return singleLayoutHelper}/*** 获取一拖N布局(最多5个Item)* 布局方式详见[GitHub->OnePlusNLayoutHelper.java](https://github.com/alibaba/vlayout/blob/master/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelper.java)*/fun getOnePlusNLayoutHelper(count: Int, colWeights: FloatArray?, rowWeight: Float): OnePlusNLayoutHelper {val onePlusNLayoutHelper = OnePlusNLayoutHelper()onePlusNLayoutHelper.itemCount = if (count > 5) 5 else countonePlusNLayoutHelper.setColWeights(colWeights)onePlusNLayoutHelper.setRowWeight(rowWeight)return onePlusNLayoutHelper}fun getOnePlusNLayoutHelper(count: Int): OnePlusNLayoutHelper {return getOnePlusNLayoutHelper(count, null, Float.NaN)}/*** 获取一拖N布局(最多7个Item)* 布局方式详见[GitHub->OnePlusNLayoutHelperEx.java](https://github.com/alibaba/vlayout/blob/master/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelperEx.java)*/fun getOnePlusNLayoutHelperEx(count: Int): OnePlusNLayoutHelperEx {return getOnePlusNLayoutHelperEx(count,null, Float.NaN)}fun getOnePlusNLayoutHelperEx(count: Int, colWeights: FloatArray?, rowWeight: Float): OnePlusNLayoutHelperEx {val onePlusNLayoutHelperEx = OnePlusNLayoutHelperEx ()onePlusNLayoutHelperEx.itemCount = if (count > 7) 7 else countonePlusNLayoutHelperEx.setColWeights(colWeights)onePlusNLayoutHelperEx.setRowWeight(rowWeight)return onePlusNLayoutHelperEx}/*** 获取吸边布局* stickyStart是否吸顶 true = 组件吸在顶部 false = 组件吸在底部*/fun getStickyLayoutHelper(stickyStart: Boolean, offset: Int): StickyLayoutHelper {val stickyLayoutHelper = StickyLayoutHelper()stickyLayoutHelper.setStickyStart(stickyStart)stickyLayoutHelper.setOffset(offset)return stickyLayoutHelper}/*** 获取瀑布流布局* count item数* lane  列数(每行条目数)*/fun getStaggeredGridLayoutHelper(count: Int, lane: Int, gap: Int): StaggeredGridLayoutHelper {return getStaggeredGridLayoutHelper(count, lane, gap, 0, 0)}fun getStaggeredGridLayoutHelper(count: Int, lane: Int, gap: Int, vGap: Int, hGap: Int): StaggeredGridLayoutHelper {val staggeredGridLayoutHelper = StaggeredGridLayoutHelper(lane)staggeredGridLayoutHelper.itemCount = countif (gap > 0) {//设置Item的间距staggeredGridLayoutHelper.setGap(gap)} else {//设置Item水平间距staggeredGridLayoutHelper.hGap = hGap//设置Item垂直间距staggeredGridLayoutHelper.vGap = vGap}return staggeredGridLayoutHelper}
}
abstract class BaseVLayoutVirtualLayoutAdapter(private val layoutManager: VirtualLayoutManager, helpers: List<LayoutHelper>) : VirtualLayoutAdapter<BaseVLayoutVirtualLayoutAdapter.BaseViewHolder>(layoutManager) {init {layoutHelpers = helpers}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {return BaseViewHolder(LayoutInflater.from(parent.context).inflate(getCustomHelperLayout(viewType), parent, false))}abstract fun getCustomHelperLayout(viewType: Int): Int/***获取指定布局位置的LayoutHelper*/fun getLayoutHelper(position: Int): LayoutHelper? {return layoutManager.findLayoutHelperByPosition(position)}/***获取指定位置的ItemView*/fun getItemView(position: Int): View? {return layoutManager.findViewByPosition(position)}override fun getItemCount(): Int {var count = 0for (layoutHelper in layoutHelpers){count += layoutHelper.itemCount}return count}override fun getItemViewType(position: Int): Int {return getItemViewType(getLayoutHelper(position)!!, position)}fun getItemViewType(@Nullable layoutHelper: LayoutHelper, position: Int): Int {return super.getItemViewType(position)}inner class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}
abstract class BaseVLayoutDelegateAdapter(private val layoutHelper: LayoutHelper) : DelegateAdapter.Adapter<BaseVLayoutDelegateAdapter.BaseViewHolder>() {override fun onCreateLayoutHelper(): LayoutHelper {return layoutHelper}fun getLayoutHelper(): LayoutHelper {return layoutHelper}override fun getItemCount(): Int {return layoutHelper.itemCount}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {@LayoutRes var layoutID = getCustomHelperLayout(layoutHelper, viewType)return BaseViewHolder(LayoutInflater.from(parent.context).inflate(layoutID, parent, false))}fun getCustomHelperLayout(layoutHelper: LayoutHelper, viewType: Int): Int {return 0}override fun getItemViewType(position: Int): Int {return getViewType(position, layoutHelper)}fun getViewType(position: Int, layoutHelper: LayoutHelper): Int {return super.getItemViewType(position)}inner class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}

参考

alibaba/vlayout:https://github.com/alibaba/vlayout

阿里VLayout学习笔记(Kotlin)相关推荐

  1. 阿里云学习笔记——设置规则引擎(2)

    标题阿里云学习笔记--设置规则引擎(2) 下面是我自己作为学习笔记分享,大神勿喷,如有叙述错误的地方欢迎指正. 1.定义Topic 定义了p_data和s_data 2.创建规则引擎,这里创建了APP ...

  2. Kotlin学习笔记--Kotlin之集合

    Kotlin学习笔记--Kotlin之集合 集合类 1. List 集合 1.1 不可变list 1.2 可变list MutableList 1.3 集合遍历 1.4 List的操作函数 1.5 l ...

  3. 超详细讲解!2579页阿里P8Android学习笔记在互联网上火了,完整版开放下载

    大家应该看过很多分享面试成功的经验,但根据幸存者偏差的理论,也许多看看别人面试失败在哪里,对自己才更有帮助. 最近跟一个朋友聊天,他准备了几个月,刚刚参加完字节跳动面试,第二面结束后,嗯,挂了- 所以 ...

  4. kotlin学习笔记——Kotlin Android Extensions

    Kotlin Android Extensions是另外一个团队开发的,它是一个插件所以不需要依赖别的库.当前仅仅包含view的绑定,会自动创建很多属性让我们直接访问xml中的view,我们就不需要明 ...

  5. 阿里DTS 学习笔记

    一.DTS是什么 DTS(Data Transmission Service, 数据传输服务),用于在关系型数据库.NoSQL数据库.数据仓库之间迁移数据. 可以使用DTS将数据迁移至阿里云,也可以在 ...

  6. 【阿里云学习笔记】快速搭建网站

    在ECS服务器上,执行以下命令安装Apache及其扩展包,run命令 yum -y install httpd httpd-manual mod_ssl mod_perl mod_auth_mysql ...

  7. Android开发六年收获阿里offer定级P7,多亏在阿里P8师兄给的攻略、面试技巧以及学习笔记!!!

    前言 又到了每年的毕业季,应届毕业生在找工作过程对于简历设计和面试技巧有一定的欠缺,这对于求职是比较重要的两个因素,因此掌握一定的面试技巧对于找互联网技术岗位的工作帮助非常大.本篇文章给大家分享一波职 ...

  8. Kotlin 学习笔记(八)—— Kotlin类与对象之接口

    Kotlin 学习笔记(八)-- Kotlin类与对象之接口 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- 基础 ...

  9. Kotlin学习笔记(3)- 语法

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

最新文章

  1. 邻接矩阵中啥时候写0和无穷_集合中的上极限与下极限
  2. 经典网页设计:20个与众不同的 Flash 网站设计作品
  3. [DiscuzNt]整合DiscuzNt论坛目前所发现的小BUG及个人简单解决办法
  4. boost::python::detail::is_string_literal相关的测试程序
  5. mr图像翻转的原因_MR的特殊检查脂肪抑制
  6. JAVA 开发axis2_基于Apache axis2开发Java Web服务
  7. (97)Verilog HDL:秒灯设计
  8. Cover Protocol首次对xCOVER进行回购
  9. 焦点关注|创造中国奇迹:北京大兴国际机场的助力者
  10. 导航标签html,导航标签
  11. HighlightPlus物体自发光
  12. 当图片被压缩时,图片变得模糊
  13. 稳健收益,缺你不可—A股优秀的基金和基金经理
  14. P5594 【XR-4】模拟赛 java题解
  15. 学习VGG(网络讲解+代码)
  16. CTF之Accept-Language规范总结
  17. 花开花落又是一度春秋,聚散离别见证一场青春。
  18. bbp代码python_如何正确计算加密债券价格的BBP(Bollinger波段百分比)?
  19. mendeley导入pdf后无法打开:unable to open this file解决办法
  20. E码通电子凭证服务平台 通用接口接入规范

热门文章

  1. pha-1 android,旧瓶装新酒,旧图新晒——当年新品现远古品 sony 大法 PHA-1
  2. Auto-Keras与AutoML: 入门指南
  3. Silverlight MMORPG网页游戏开发课程[一期] 第十一课:战斗系统之脚本与精灵捕获...
  4. 安装Windows+Ubuntu18.04双系统(双盘)及grub引导修复
  5. zabbix5.0的安装与实现
  6. CG软件blender入门教程
  7. linux 内核驱动 调试,QDMA Linux 内核驱动使用和调试指南
  8. Java基础第十一章----集合
  9. docker原理与实现
  10. Vikings V2用户手册