Google FlexboxLayout

repository·main·Indexed 12 days ago

https://github.com/google/flexbox-layout

Brings CSS Flexible Box Layout Module capabilities to Android, providing flexible layout management for standard ViewGroups and RecyclerViews. It includes FlexboxLayout for direct ViewGroup replacement and FlexboxLayoutManager for memory-efficient view recycling in RecyclerViews. Supports attributes such as flexDirection, flexWrap, justifyContent, and layout_flexBasisPercent.

Tokens
3.4K
Snippets
7
Records
14
Agent score
97%

What's inside FlexboxLayout

  1. Understand differences between FlexboxLayout and CSS Flexbox

    main

    While FlexboxLayout aims for compatibility with the W3C Flexible Box specification, there are key differences due to Android XML constraints:

    1. No shorthand attributes: There are no direct equivalents for CSS flex-flow (which combines direction and wrap) or flex (which combines grow, shrink, and basis). You must specify the individual attributes instead.
    2. layout_flexBasisPercent vs flex-basis: Unlike CSS which accepts various units (em, px, content), layout_flexBasisPercent only accepts percentage values. For fixed sizes or content behavior, use standard layout_width/layout_height or wrap_content.
    3. layout_wrapBefore: This is an Android-specific addition for better control over line breaks.
    4. Default Alignment: The default values for alignItems and alignContent are set to flex_start instead of stretch to improve measurement performance in deep layout hierarchies.
  2. Install FlexboxLayout

    main

    Add the Flexbox dependency to your build.gradle file.

    Important Notes:

    • GroupId Change: Starting from version 3.0.0, the groupId is com.google.android.flexbox. Older versions used com.google.android and are available on jcenter.
    • AndroidX: Version 1.1.0 and above require AndroidX. If your project has not migrated to AndroidX, use version 1.0.0.
    • Breaking Change: Starting from 2.0.0, the default values for alignItems and alignContent changed from stretch to flex_start. If you require the stretch behavior, you must set it explicitly.
    dependencies {
        implementation 'com.google.android.flexbox:flexbox:3.0.0'
    }
  3. Use FlexboxLayout as a ViewGroup

    main

    You can use FlexboxLayout as a direct replacement for LinearLayout or RelativeLayout by extending ViewGroup. It can be configured via XML attributes or programmatically in Java/Kotlin.

    XML Usage: Use the app: namespace to define flex properties like flexWrap, alignItems, and alignContent on the container, and app:layout_* properties on the children.

    Programmatic Usage: To modify a child's layout properties in code, cast its LayoutParams to FlexboxLayout.LayoutParams.

    <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" />
    </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.setOrder(-1);
    lp.setFlexGrow(2);
    view.setLayoutParams(lp);
  4. Run the Cat Gallery demo app

    main

    The demo-cat-gallery module demonstrates how to use FlexboxLayoutManager within a RecyclerView. This approach is memory-efficient (similar to Google Photos) and helps avoid OutOfMemoryError compared to using a standard FlexboxLayout for large lists.

    ./gradlew demo-cat-gallery:installDebug
    #!/bin/bash
    ./gradlew demo-cat-gallery:installDebug
  5. Run the Flexbox Playground demo app

    main

    The demo-playground module is a playground app designed to help you test various attribute values. You can install and run it using the following command:

    ./gradlew demo-playground:installDebug
    #!/bin/bash
    ./gradlew demo-playground:installDebug
  6. Configure FlexboxLayout container attributes

    main

    The following attributes control the behavior of the FlexboxLayout container:

    • flexDirection: Determines the direction of the main and cross axes. Values: row (default), row_reverse, column, column_reverse.
    • flexWrap: Controls if the container is single-line or multi-line. Values: nowrap (default for FlexboxLayout), wrap (default for FlexboxLayoutManager), wrap_reverse (not supported by FlexboxLayoutManager).
    • justifyContent: Alignment along the main axis. Values: flex_start (default for FlexboxLayout), flex_end, center, space_between, space_around, space_evenly.
    • alignItems: Alignment along the cross axis. Values: flex_start (default for FlexboxLayout), flex_end, center, baseline, stretch (default for FlexboxLayoutManager).
    • alignContent: Alignment of flex lines in the container. Values: flex_start (default), flex_end, center, space_between, space_around, stretch.
    • Dividers:
      • showDividerHorizontal / showDividerVertical: Set to none, beginning, middle, or end.
      • dividerDrawableHorizontal / dividerDrawableVertical: Reference to a drawable.
      • showDivider / dividerDrawable: Shorthand for both horizontal and vertical dividers. Warning: Avoid using these simultaneously with justifyContent="space_around" or alignContent="space_between" to prevent unexpected spacing.
  7. Configure attributes for FlexboxLayout children

    main

    When using FlexboxLayout, you can control the behavior of individual child views using specific layout_ prefixed attributes in your XML layout. These attributes allow you to manage ordering, growth, shrinking, alignment, and sizing constraints.

    Ordering and Sizing

    • layout_order (integer): Changes the visual order of children. Defaults to 1.
    • layout_flexGrow (float): Determines how much a child grows to fill positive free space in a flex line. Defaults to 0. Similar to layout_weight in LinearLayout.
    • layout_flexShrink (float): Determines how much a child shrinks when negative free space is distributed. Defaults to 1.
    • layout_flexBasisPercent (fraction): Sets the initial main size of the child as a fraction of the parent's size. This overrides layout_width or layout_height. Only effective when the parent's size is definite (MeasureSpec.EXACTLY). Defaults to -1 (not set).
    • layout_minWidth / layout_minHeight (dimension): Imposes minimum size constraints that layout_flexShrink cannot override.
    • layout_maxWidth / layout_maxHeight (dimension): Imposes maximum size constraints that layout_flexGrow cannot override.
    <!-- Example of child attributes in XML -->
    <com.google.android.flexbox.FlexboxLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <View
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_flexGrow="1.0"
            app:layout_order="2"
            app:layout_minWidth="50dp" />
    
    </com.google.android.flexbox.FlexboxLayout>
  8. Align child views along the cross axis with layout_alignSelf

    main

    The layout_alignSelf attribute allows a child view to override the alignment set by the parent's alignItems property along the cross axis (perpendicular to the main axis).

    Possible values for layout_alignSelf:

    • auto (default): Uses the parent's alignItems value.
    • flex_start
    • flex_end
    • center
    • baseline
    • stretch
  9. Configure Flexbox child attributes

    main

    Children within a FlexboxLayout or FlexboxLayoutManager can be customized using specific layout parameters.

    For FlexboxLayout (XML):

    • app:layout_flexBasisPercent: Sets the basis size as a percentage.
    • app:layout_alignSelf: Overrides the container's alignItems for this specific child. Values: flex_start, flex_end, center, etc.
    • app:layout_flexGrow: Defines how much the child should grow relative to siblings.
    • app:layout_flexShrink: Defines how much the child should shrink.
    • app:layout_wrapBefore: Forces the item to wrap to a new line.
    • app:layout_order: Sets the visual order of the item.

    For FlexboxLayoutManager (Programmatic): When using RecyclerView, cast LayoutParams to FlexboxLayoutManager.LayoutParams to access:

    • setFlexGrow(float)
    • setAlignSelf(AlignSelf)
  10. Force line wrapping with layout_wrapBefore

    main

    The layout_wrapBefore attribute (boolean) forces a flex line wrap. When set to true, the item becomes the first item of a new flex line, regardless of whether the previous items would have fit.

    Note: This attribute is ignored if the parent's flex_wrap attribute is set to nowrap. This is a specialized Android feature not present in the original CSS specification, useful for creating grid-like layouts or semantic breaks.

  11. Use FlexboxLayoutManager with RecyclerView

    main

    For large datasets, use FlexboxLayoutManager within a RecyclerView. This implementation enables view recycling, which significantly reduces memory consumption compared to FlexboxLayout by only inflating views currently visible on screen.

    Note on Limitations: Due to RecyclerView constraints, FlexboxLayoutManager does not support alignContent, layout_order, or `flexWrap=

  12. Handle FlexItem order reordering

    main

    When using FlexItem#getOrder(), the layout order of children may differ from their index in the parent ViewGroup. You can use createReorderedIndices to obtain an array of indices that accounts for these order attributes. This is useful when you need to map between the actual child positions and their logical flex order.

    To use this, you typically interact with a FlexboxHelper instance associated with your FlexContainer (like FlexboxLayout).

    // Note: FlexboxHelper is package-private, but its logic is used by 
    // FlexboxLayout and FlexboxLayoutManager to handle reordering.
    // The reordered indices array reflects the order defined by FlexItem.getOrder().
    int[] reorderedIndices = flexboxHelper.createReorderedIndices(orderCache);