FlexBoxlayout是Google推出的开源的可伸缩性布局,在项目中也会经场使用,大大提高了用户的体验。

compile 'com.google.android:flexbox:1.0.0'

有前端基础的同学估计都知道 CSS 中这个布局,用来为盒状模型提供最大的灵活性。因为 android 中这个库属性和 CSS 中 都一样,并且阮一峰老师写的前端知识真的很通俗易懂,所以这里的介绍大多来自 Flex 布局教程。

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称”项目”。

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。这里与 react native 相反,与前端 CSS 保持一致。

主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end

项目默认沿主轴排列。单个项目占据的主轴空间叫做 main size,占据的交叉轴空间叫做 cross size。

2.容器的属性 (FlexboxLayout 属性介绍)

这里说的容器也就是上面的采用了 Flex 布局的元素,在 android 中也就是引用了 FlexboxLayout 的 控件。即 FlexboxLayout 控件支持的属性。主要属性有:

各个属性的详细含义这里就不再赘述,阮一峰老师 这篇文章 写的超级棒,图文并茂,很容易理解,推荐大家看一下。

3.项目的属性 (子 View 属性介绍)

设置被 FlexboxLayout 包裹的子 View 的属性,因为 android 中的 flexboxLayout 布局 和 CSS 中 flex 布局关于子 View 属性有些差异,所以这里详细说明下,取值如下:

  • layout_order (integer)
  • layout_flexGrow (float)
  • layout_flexGrow (float)
  • layout_alignSelf
  • layout_flexBasisPercent (fraction)
  • layout_minWidth / layout_minHeight (dimension)
  • layout_maxWidth / layout_maxHeight (dimension)
  • layout_wrapBefore (boolean)

下面来看一下github文档中对这些属性的描述

3.1 layout_order

这个属性可以改变布局子视图的顺序。默认情况下,子元素的显示和布局顺序与布局XML中的顺序相同。如果没有指定,则将1设置为默认值( CSS 中默认值为 0) ,数值越小,排列越靠前

看下文档中的这张图,可以看到将 “2” 号 View 的 layout_order 属性设置为 -1时,由于其他的 View 默认都是 1,所以 “2” 号 view会排在最前面,同理,将 “2” 号 View 的 layout_order 的属性值设为 2 时,比其他默认值 1 都大,所以会排在最后。

3.2 layout_flexGrow

这个属性类似于 LinearLayout 中的 layout_weight 属性,如果没有指定,则将 0 设置为默认值。如果果同一 flex 行中的多个子 View 有正的 layout_flexGrow 值,那么剩余的空闲空间将根据它们声明的 layout_flexGrow 值的比例分布。

3.3 layout_flexShrink

该属性定义了子 View 的缩小比例,默认为 1,即如果空间不足,该子 View 将缩小。
如果所有子 View 的 layout_flexShrink 属性都为 1,当空间不足时,都将等比例缩小。如果一个项目的 layout_flexShrink 属性为0,其他子View都为 1,则空间不足时,layout_flexShrink 属性为 0 的不缩小。

看一下文档中的这张图,开始设置所有子 view 的 layout_flexShrink 属性为1,添加子 view 的时候所有子 view 等比缩小,但是如果设置 layout_flexShrink 属性值为 0,子 view 将会按照原有比例显示,不缩小。

3.4 layout_alignSelf

layout_alignSelf 属性允许单个子 View 有与其他 View 不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。
该属性可能取 6 个值,除了 auto,其他都与 align-items 属性完全一致

3.5 layout_flexBasisPercent

flex-layout_flexBasisPercent 属性定义了在分配多余空间之前,子 View 占据的主轴空间(main size)。根据这个属性来计算主轴是否有多余空间。它的默认值为 -1,即不设置,采用子 View 的本来大小。

如果设置了这个值,layout_width (或 layout_height )中指定的长度将被该属性的计算值覆盖。这个属性只有在父 View 的长度是确定的时候才有效(测量模式是 MeasureSpec.EXACTLY 模式下)。
并且该属性值只接受百分比值。

可以分析下文档中的这张图:可以看到,如果把中间子 View 的这个属性值设为 50% 或 90%,那么这个 View 将占据主轴 50% 或 90% 的空间,然后剩余 View 会看有没有剩余空间换行。如果设置为 -1 默认值,那么将占据给定的大小。

3.6 layout_minWidth / layout_minHeight

这个属性设置了子 View 的最小的宽和高。在 layout_flexShrink 模式下,再怎么缩小也不会小于这个值

3.7 layout_maxWidth / layout_maxHeight

这个属性设置了子 View 的最大的宽和高。在 layout_flexGrow 模式下,再怎么放大也不会大于这个值

3.8 layout_wrapBefore

这个属性使得子 View 可以强制换行,不管在 main size 剩余空间有多少。这种对于类似 grid 网格布局中特殊设置某一个 item 布局特别有用。
这个属性是 CSS 中没有的属性。该属性在 flex_wrap 属性值 为 nowrap(不换行)的时候是无效的。
该属性结束 boolean 变量,默认 false,即不强制换行

分析下文档中的这张图,“5” 号和 “6” 号 View 设置 layout_wrapBefore 属性为ture 的时候,不管前面剩余多少空间,都会强制换行

到这里,flexboxLayout 基本属性就介绍完毕了。

然后再来介绍一下跟 recycleView 结合使用。

4. 高能:与 RecyclewView 结合使用

Flexbox 能够作为一个 LayoutManager(FlexboxlayoutManager) 用在 RecyclerView 里面,这也就意味着你可以在一个有大量 Item 的可滚动容器里面使用 Flexbox,提高性能。具体使用示例:

 
  1. 1

  2. 2

  3. 3

  4. 4

  5. 5

  6. 6

  7. 7

  8. 8

  9. 9

  10. 10

 
  1. //设置主轴方向为横轴

  2. FlexboxLayoutManager manager = new FlexboxLayoutManager(this, FlexDirection.ROW);

  3. //设置item沿主轴方向的位置

  4. manager.setJustifyContent(JustifyContent.CENTER);

  5. //设置item 沿次轴方向的位置

  6. manager.setAlignItems(AlignItems.CENTER);

  7. recycleView.setLayoutManager(manager);

  8. centerGridAdapter = new CenterGridAdapter(items, this);

  9. recycleView.setAdapter(centerGridAdapter);

可以看到跟 RecycleView 的其他 manager 使用一样,只需设置 manager 属性即可,属性值为上面叙述的几个容器的属性。
如果想对某个 item 进行单独的设置,可以在 adapter 中去设置,设置示例代码为:

 
  1. 1

  2. 2

  3. 3

  4. 4

  5. 5

  6. 6

 
  1. ViewGroup.LayoutParams lp = holder.itemLL.getLayoutParams();

  2. if (lp instanceof FlexboxLayoutManager.LayoutParams) {

  3. FlexboxLayoutManager.LayoutParams flexboxLp =

  4. (FlexboxLayoutManager.LayoutParams) holder.itemLL.getLayoutParams();

  5. flexboxLp.setFlexGrow(1.0f);

  6. }

我这里是设置每个 item 有个权重(相当于 Linearlayout 的 weight 属性),所以会按比例分配 item 的宽,而不是我布局中设定的固定宽高。看下效果:

是不是有种键盘的感觉?并且我只是修改了极少的代码就实现了这个功能。

小试牛刀1

最后,看了那么多,回到最开始的问题上,现在知道类似微信的那个中间扩展的网格布局怎么写的吗?
首先我们简单分析一下,

  • 主轴方向我们应该设置为水平方向,即默认 flexDirection :“row”’
  • 可以换行,即 flexWrap:“wrap”
  • 子 View 在主轴方向的对其方式为居中(这一步实现从中间往两边展开),即 justifyContent: “center”
  • 子 View 在交叉轴方向的对其方式为居中,即 alignItems:”center”
  • 子 View 宽高固定

也就是上面讲 Recycleview 结合的例子中去掉单独设置 item 的部分,并且 item 的宽高要根据屏幕来适配的。
嗯,就是 so easy。

小试牛刀2

实际应用中还有种很常见的就是那种分类选择的布局,像图中的网易和简书中,这种布局用我们今天的这个主角是不是轻而易举的就实现了?都不用设置特别的属性,内容超过一行自动换行。
代码如下:

 
  1. 1

  2. 2

  3. 3

  4. 4

  5. 5

  6. 6

  7. 7

  8. 8

  9. 9

  10. 10

 
  1. //设置主轴方向为横轴

  2. FlexboxLayoutManager manager = new FlexboxLayoutManager(this, FlexDirection.ROW);

  3. //设置item沿主轴方向的位置

  4. manager.setJustifyContent(JustifyContent.FLEX_START);

  5. //设置item 沿次轴方向的位置

  6. manager.setAlignItems(AlignItems.CENTER);

  7. recycleView.setLayoutManager(manager);

  8. labelAdapter = new LabelAdapter(labels,this);

  9. recycleView.setAdapter(labelAdapter);

小试牛刀3

以项目需求为例,如图所示:

                          

在第一张需求图中,品牌筛选时 最后有一个”+“号,想要的效果时 根据品牌选择后,这个”+“号会紧挨着显示,如果显示不完,就换行显示。

刚开始考虑的是的在RecyclerView添加FooterView,FooterView为一个“+”的按钮,这个按钮会换一行显示,不能紧挨着显示,如果超过一行再换行显示。

此时会遇到两个问题,

按照RecyclerView中的基本用法使用后 会报错,日志如下:

ClassCastException: android.support.v7.widget.RecyclerView$LayoutParams cannot be cast to com.google.android.flexbox.FlexItem。

我们添加的FooterView,无法转换成FlexlItem。网上找到解决方案,详情见FlexboxLayoutManager 踩坑。

一是需要重写FlexboxLayoutManager,代码示例如下:

 
  1. import com.google.android.flexbox.FlexboxLayoutManager

  2. class MyFlexboxLayoutManager : FlexboxLayoutManager {

  3. constructor(context: Context) : super(context)

  4. constructor(context: Context, flexDirection: Int) : super(context, flexDirection)

  5. constructor(context: Context, flexDirection: Int, flexWrap: Int) : super(context, flexDirection, flexWrap)

  6. /**

  7. * 将LayoutParams转换成新的FlexboxLayoutManager.LayoutParams

  8. */

  9. override fun generateLayoutParams(lp: ViewGroup.LayoutParams): RecyclerView.LayoutParams {

  10. return when (lp) {

  11. //TODO:可能需要适配,特殊处理"+"的宽度

  12. is RecyclerView.LayoutParams -> LayoutParams(lp)

  13. is ViewGroup.MarginLayoutParams -> LayoutParams(lp)

  14. else -> LayoutParams(lp)

  15. }

  16. }

  17. }

第二个问题:显示问题。此时会出现我们的FooterView(”+“号)换一行显示,不能紧挨着显示。

于是陷入思考,在上述代码中,RecyclerView.LayoutParams的计算方法LayoutParams(lp)也需要重写。

在查阅资料和源码后发现比较麻烦,最后在网友的帮助下(FlexboxLayoutManager 踩坑),换一种思路,用RecyclerView多布局来实现,豁然开朗。

思路如下:在数据实体类中添加一个标志,如是否是添加标志isAdd,根据该值的是不同显示不同的item布局。

 
  1. class CameraVehicleBrandAdapter : MyBaseMultiItemAdapter<CameraVehicleBrandEntity>() {

  2. init {

  3. addItemType(CameraVehicleBrandEntity.ITEM_TYPE_NORMAL, R.layout.home_recycle_item_camera_vehicle_brand_selected)

  4. addItemType(CameraVehicleBrandEntity.ITEM_TYPE_ADD, R.layout.home_recycle_item_camera_vehicle_brand_add)

  5. }

  6. override fun convert(helper: BaseViewHolder, item: CameraVehicleBrandEntity) {

  7. super.convert(helper, item)

  8. if (item.isAdd) {

  9. helper.addOnClickListener(R.id.ivAddBrand)

  10. return

  11. }

  12. helper.setText(R.id.tvBrandName, item.brandName)

  13. helper.addOnClickListener(R.id.ivDelete)

  14. }

  15. }

调用方法:

 
  1. //品牌筛选

  2. rvBrand.layoutManager = FlexboxLayoutManager(context)

  3. rvBrand.adapter = brandAdapter

总结

所以说了这么多,那么我们什么时候会用到这种布局呢?我目前想到的场景主要有 3 类:

  1. 类似LinearLayout 线性布局,但是又可以自动换行的
  2. 类似grid 网格布局的,但总有一两个item的排列方式很特立独行的
  3. 类似瀑布流的,但也是总有一两个item跟别人不一样的

当然这些场景加上 RecycleView 就会更加畅享丝滑了。

详细了解 Android 巧用 flexboxLayout 布局相关推荐

  1. Android 巧用 flexboxLayout 布局

    FlexBoxlayout是Google推出的开源的可伸缩性布局,在项目中也会经场使用,大大提高了用户的体验. compile 'com.google.android:flexbox:1.0.0' 有 ...

  2. android布局时长分析,Android性能优化:布局优化 详细解析(含、、讲解 )

    前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的布局优化,希望你们会喜欢. 目录 1. 影响的性能 布局性能的好坏 主要影响 :Android应用中的页面显示速度 2. ...

  3. android recyclerview流式布局,Android FlexboxLayout流式布局

    Android FlexboxLayout流式布局 FlexBoxLayout是为Android带来了与 CSS Flexible Box Layout(CSS 弹性盒子)相似功能的库. 一:添加依赖 ...

  4. 【Android 性能优化】布局渲染优化 ( GPU 过度绘制优化总结 | CPU 渲染过程 | Layout Inspector 工具 | View Tree 分析 | 布局组件层级分析 )

    文章目录 一. GPU 过度绘制优化总结 二. CPU 渲染过程 三. CPU 渲染性能调试工具 Layout Inspector 四. Layout Inspector 组件树 DecorView ...

  5. android自定义通知栏图标大小,Android不使用自定义布局情况下实现自定义通知栏图标的方法...

    本文实例讲述了Android不使用自定义布局情况下实现自定义通知栏图标的方法.分享给大家供大家参考,具体如下: 自定义通知栏图标?不是很简单么.自定义布局都不在话下! 是的,有xml布局文件当然一切都 ...

  6. 2021年最详细的Android屏幕适配方案汇总

    1 Android屏幕适配的度量单位和相关概念 建议在阅读本文章之前,可以先阅读快乐李同学写的文章<Android屏幕适配的度量单位和相关概念>,这篇文章包含了阅读本文的一些基础知识,推荐 ...

  7. Carson带你学Android:请收好这一份全面详细的Android学习指南

    前言 如果你也学习Android,那么你大概率会看过我的文章.经常有读者给我留言:"该怎么学习Android?"."日常学习Android的方法是什么". 今天 ...

  8. Android studio百度地图SDK开发 2020最新超详细的Android 百度地图开发讲解(3) 路线规划步行骑行驾车路线规划

    2020最新超详细的Android 百度地图开发讲解(3) 路线规划步行骑行驾车路线规划 开发前配置,显示基本地图,实时定位等查看之前代码,此博客紧接上一博客:https://blog.csdn.ne ...

  9. 面试汇总:这是一份全面详细的Android面试指南

    核心面试内容 对于Android技术专业面试,主要考察的内容包括:(已按优先级排序) 通用编程基础 计算机基础 特定编程语言 智力题 需要特别注意的是: 编程基础.计算机基础是 所有技术开发都必备的基 ...

最新文章

  1. react生命周期和组件生命周期
  2. linux 占用缓存前10_Linux 中的零拷贝技术
  3. python 计算 IOU
  4. create-react-app部署到GitHub Pages时报错:Failed to get remote。origin.url
  5. 10 个最佳的 Node.js 的 MVC 框架
  6. mysql stack is full_mysql优化之表的优化与列类型选择
  7. 对话框控件访问七种方式
  8. #CSP 201709-1 打酱油
  9. 【译】技能测试解决方案:Python中的数据科学(一)
  10. 炸群java脚本,跪求微信炸群代码_跪求以下java程序的源代码
  11. dorado7.x控制显示隐藏
  12. 基于移动通信数据的城市可视分析研究
  13. 手机内存文件夹html,手机内存难清理?试试直接删掉这3个文件夹,网友:咋不早说?...
  14. 常用的统计抽样分布和正态总体的抽样分布
  15. java aes ebc_Delphi XE2+标准AES加解密算法(AES/EBC,CBC/PKCS5Padding-base64)
  16. 风起看云涌,叶落品人生 - Google 搜索
  17. freeswitch的呼叫中心模块——mod_callcenter
  18. ROS基础教程-官网翻译版
  19. Project Babel通天塔计划亮相2022全球元宇宙大会
  20. 关于代码动态修改xib内控件尺寸

热门文章

  1. win10/ubuntu18.04 双系统开机黑屏,无法通过grub 选择系统,直接进入Ubuntu系统
  2. Java线程等待唤醒机制(加深理解)
  3. 拉普拉斯变换的定义-笔记
  4. “对不起,我是用AI做的警察”
  5. 江苏警官学院计算机科学与技术专业,江苏警官学院什么专业好就业,哪些专业适合女生...
  6. 动态背景下的运动目标检测
  7. kerastensorflow+分布式训练︱实现简易视频内容问答框架
  8. html网页抓取建一个网站前端,创建网页的方法以及生成HTML骨架
  9. “跨次元”检测模型hold住各种画风,真人赛博,在线Demo可玩
  10. web前端基础——超链接(dw笔记版)