FlexboxLayout的使用

FlexboxLayout

本文是官方文档的翻译

FlexboxLayout 是一个库项目,能在Android上实现类似CSS Flexible Box Layout Module 的能力。

安装

添加以下依赖到你的build.gradle 文件中:

dependencies {
    implementation 'com.google.android:flexbox:1.0.0'
}

使用

在布局中有两种方式使用FlexBox

FlexboxLayout

第一种是像LinearLayoutRelativeLayout那样,FlexboxLayout 都是继承了 ViewGroup
你可以指定属性在一个布局XML,如:

<com.google.android.flexbox.FlexboxLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:flexWrap="wrap"
    app:alignItems="stretch"
    app:alignContent="stretch" >

    <TextView
        android:id="@+id/textview1"
        android:layout_width="120dp"
        android:layout_height="80dp"
        app:layout_flexBasisPercent="50%"
        />

    <TextView
        android:id="@+id/textview2"
        android:layout_width="80dp"
        android:layout_height="80dp"
        app:layout_alignSelf="center"
        />

    <TextView
        android:id="@+id/textview3"
        android:layout_width="160dp"
        android:layout_height="80dp"
        app:layout_alignSelf="flex_end"
        />
com.google.android.flexbox.FlexboxLayout>

或者通过代码像:

FlexboxLayout flexboxLayout = (FlexboxLayout) findViewById(R.id.flexbox_layout);
flexboxLayout.setFlexDirection(FlexDirection.ROW);

View view = flexboxLayout.getChildAt(0);
FlexboxLayout.LayoutParams lp = (FlexboxLayout.LayoutParams) view.getLayoutParams();
lp.order = -1;
lp.flexGrow = 2;
view.setLayoutParams(lp);

FlexboxLayoutManager (within RecyclerView)

第二种方式是 FlexboxLayoutManager 可以使用在 RecyclerView的内部.

RecyclerView recyclerView = (RecyclerView) context.findViewById(R.id.recyclerview);
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(context);
layoutManager.setFlexDirection(FlexDirection.COLUMN);
layoutManager.setJustifyContent(JustifyContent.FLEX_END);
recyclerView.setLayoutManager(layoutManager);

或者通过孩子的属性的 FlexboxLayoutManager 你可以这样做:

mImageView.setImageDrawable(drawable);
ViewGroup.LayoutParams lp = mImageView.getLayoutParams();
if (lp instanceof FlexboxLayoutManager.LayoutParams) {
    FlexboxLayoutManager.LayoutParams flexboxLp = (FlexboxLayoutManager.LayoutParams) lp;
    flexboxLp.setFlexGrow(1.0f);
    flexboxLp.setAlignSelf(AlignSelf.FLEX_END);
}

使用FlexboxLayoutManager的优点是它可以回收从屏幕上消失的views,为了重用那些出现在用户滚动条上的视图而不是每次都inflate每个单独的view,
这样做可以消耗小得多的内存特别是当Flexbox容器包含了item的总数是很大的时候。

支持的属性/功能特征

由于RecyclerView的一些特征,有些FlexBox的属性不可用或者没有实现在FlexboxLayoutManager
下面是两个实现之间的属性/特性比较的快速概述

Attribute / Feature FlexboxLayout FlexboxLayoutManager (RecyclerView)
flexDirection
flexWrap (except wrap_reverse)
justifyContent
alignItems
alignContent -
layout_order -
layout_flexGrow
layout_flexShrink
layout_alignSelf
layout_flexBasisPercent
layout_(min/max)Width
layout_(min/max)Height
layout_wrapBefore
Divider
View recycling -
Scrolling *1

*1 部分可能用ScrollView来包装,但是它不太可能用作与一个大集合布局内部的视图,因为它不考虑到视图的回收

支持的属性

Attributes for the FlexboxLayout:

  • flexDirection

    • 这个属性决定了主轴的方向(交叉轴,垂直于主轴。子items根据方向放置到Flexbox布局中
      可能的值有:
    • row (default)
    • row_reverse
    • column
    • column_reverse

  • flexWrap

    • 这个属性控制flex container 是单行或者多行,和交叉轴的方向,可能的值有:
    • nowrap (default)
    • wrap
    • wrap_reverse

  • justifyContent

    • 这个属性控制主轴的对齐方式,可能的值有:
    • flex_start (default)
    • flex_end
    • center
    • space_between
    • space_around

  • alignItems

    • 这个属性控制交叉轴的对齐方式,可能的值:
    • stretch (default)
    • flex_start
    • flex_end
    • center
    • baseline

  • alignContent

    • 这个值控制flex的lines对齐方式在fiex容器中(只有多行的时候有效),可能的值:
    • stretch (default)
    • flex_start
    • flex_end
    • center
    • space_between
    • space_around

  • showDividerHorizontal (one or more of none | beginning | middle | end)

  • dividerDrawableHorizontal (reference to a drawable)
    *在flex线之间放置水平分隔物 (or flex items when flexDirection
    is set to column or column_rebase).

  • showDividerVertical (one or more of none | beginning | middle | end)

  • dividerDrawableVertical (reference to a drawable)

    • 在flex项目之间放置垂直分隔物 (or flex lines when flexDirection
      is set to column or column_rebase).
  • showDivider (one or more of none | beginning | middle | end)

  • dividerDrawable (reference to a drawable)

    • 同时设置水平和垂直的分割线。注意,如果与其他属性一起使用
      (such as justifyContent="space_around" or alignContent="space_between" … etc) 将
      在flex线或flex项目之间的空间,您可能会看到意想不到的空间。请避免使用这些
      在同一时间。

    同时放置水平和垂直分割线的例子。

    res/drawable/divider.xml

    <shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size
        android:width="8dp"
        android:height="12dp" />
    <solid android:color="#44A444" />
    shape> 

    res/layout/content_main.xml

    <com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:alignContent="flex_start"
    app:alignItems="flex_start"
    app:flexWrap="wrap"
    app:showDivider="beginning|middle"
    app:dividerDrawable="@drawable/divider" >
    
    <TextView
        style="@style/FlexItem"
        android:layout_width="220dp"
        android:layout_height="80dp"
        android:text="1" />
    <TextView
        style="@style/FlexItem"
        android:layout_width="120dp"
        android:layout_height="80dp"
        android:text="2" />
    <TextView
        style="@style/FlexItem"
        android:layout_width="160dp"
        android:layout_height="80dp"
        android:text="3" />
    <TextView
        style="@style/FlexItem"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:text="4" />
    <TextView
        style="@style/FlexItem"
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:text="5" />

FlexboxLayout子View的属性

  • layout_order (integer)

    • 这个属性能改变子views布局的顺序,默认子view显示放置相同的顺序跟他们在XML声明的一样。

  • layout_flexGrow (float)

    • 这个属性决定了子view将增大多少,如果可分配的空间还有多余时根据相对于其他的flex的同一行的items,
      如果一个flex的item 有一个正数layout_flexGrow的值,在flex行中这个item将占据剩余的部分。如果相同
      的flex一行有多个flex items有layout_flexGrow正数的值,剩下的自由的空间分配根据他们声明的layout_flexGrow 值得比例。(类似 LinearLayoutlayout_weight属性)如果不指定,这个值默认设置为0
  • layout_flexShrink (float)

    • 这个属性决定了子view将缩小多少,如果可分配的空间不足时的时候相对于其他的flex的同一行的items.
      如果没有指定,默认值设置为1
  • layout_alignSelf

    • 这个属性决定了交叉轴(垂直于主轴)的对齐方式。在同方向对齐可以根据父的alignItems决定,但是如果这个属性设置了
      其他的属性除了auto,交叉轴的对齐将会被子view重写,可能的值:
    • auto (default)
    • flex_start
    • flex_end
    • center
    • baseline
    • stretch

  • layout_flexBasisPercent (fraction)

    • 初始的flex的item长度用一个分数的格式相对于他的父长度,这个子view的初始主要大小尝试扩展根据指定的分数相对于父的
      主要大小。
      如果这个值设置了,从layout_width(或者 layout_height)指定的长度会被重写通过这个分数计算的到的值。
      这个属性仅当父的长度明确时才有效(MeasureSpec mode isMeasureSpec.EXACTLY)。默认值是-1,以为着不设置。

  • layout_minWidth / layout_minHeight (dimension)

    • 这些属性为FlexboxLayout的孩子设置了最小尺寸限制,一个孩子,不能收缩小于这些属性的值(变化的基础上flexDirection属性是指哪个属性将大小限制强加于主轴),不管layout_flexShrink属性

  • layout_maxWidth / layout_maxHeight (dimension)

    • 这些属性为FlexboxLayout的孩子设置了最大尺寸限制,一个孩子,不能伸展大于这些属性的值(变化的基础上flexDirection属性是指哪个属性将大小限制强加于主轴),不管layout_flexGrow属性

  • layout_wrapBefore (boolean)

    • 这个属性强制一个flex线包装,默认值是“false”。也就是说,如果这个被设置为“true”
      flex项目,这个项目将成为flex系列的第一个项目。(包装情况不考虑在之前的flex系列中处理的flex项目)
      如果“flexwrap”属性设置为“nowrap”,则忽略该属性。在原来的CSS灵活框模块中没有定义等效属性规范,
      但是拥有这个属性对于Android开发人员是很有用的。例如,压平在构建网格状布局时的布局,或者是开发人
      员想要的情况为了使一个新的flex线与前一个的语义不同,等等。

Others

与原始CSS规范的已知差异

这个库尝试尽可能跟原
Flexible Box specification 功能相同,
但是由于某些原因,比如指定属性的方式在这两者之间是不一样的
CSS和Android XML,与原始规范有一些已知的区别

(1) 没有与 flex-flow
等效的属性
* 因为flex-flow是设置flex-directionflex-wrap属性的缩写,
从单个属性中指定两个属性在Android中是不实用的。

(2) 没有flex 等效属性
* 同样的,flex 是设置flex-growflex-shrinkflex-basis的缩写,
从单个属性中指定这些属性是不实际的。

(3)layout_flexBasisPercent被引入,而不是
flexBasis
* 本库中的layout_flexBasisPercent和CSS中的flex-basis属性都被用于
确定单个flex项目的初始长度。flex-basis属性接受宽度
诸如1em10pxcontent等值,以及诸如此类的百分比值
“10%”和“30%”。layout_flexBasisPercent只接受百分比值。
但是,指定初始固定宽度值可以通过指定宽度(或高度)值来完成
layout_width(或layout_height,取决于flexDirection)。同时,相同的
layout_width(或layout_height)中指定”wrap_content”来实现效果。
开发人员想要达到与 ‘content’相同的效果。因此,只有layout_flexBasisPercent
接受百分比值,这不能通过ayout_width(或layout_height)来简单完成

(4) layout_wrapBefore 已经介绍.
* 在CSS灵活的Box模块规范中不存在等价的属性,
但正如上面所解释的,Android开发者将会受益于拥有这个属性
当包装发生时,更多的控制。

你可能感兴趣的:(Android开发)