Yamin Siahmargooei
Yamin Siahmargooei

Reputation: 3707

Divider decoration for constraint layout flow helper children

As you may know, you can set a RecyclerView.ItemDecoration for RecyclerView's Items. However, I want to achieve something similar to that but for ConstraintLayout's Flow.

Currently, I can create multiple divider views and put them inside my flow after each normal view but that can be cumbersome when my Flow has multiple views and that's not DRY and is an example of repeating yourself. Also, it's worth noting that you cannot reference the same view more than once in Flow so you cannot create a divider view and reference it multiple times in different positions. Pragmatically I can create a custom background/style for TextView with a line under them to somehow replicate a divider but what if Flows children are not TextView?

flow with repeating dividers

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="4dp"
    android:checkable="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.constraintlayout.helper.widget.Flow
            android:id="@+id/product_item_detail_flow"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp"
            android:orientation="vertical"
            android:padding="8dp"
            app:constraint_referenced_ids="product_item_category,materialDivider,product_item_name,materialDivider2,product_item_price"
            app:flow_verticalGap="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/product_item_image"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <com.google.android.material.divider.MaterialDivider
            android:id="@+id/materialDivider"
            android:layout_width="0dp"
            android:layout_height="wrap_content" />

        <com.google.android.material.divider.MaterialDivider
            android:id="@+id/materialDivider2"
            android:layout_width="0dp"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/product_item_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="18sp"
            tools:text="@tools:sample/lorem" />

        <TextView
            android:id="@+id/product_item_category"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="14sp"
            tools:text="@tools:sample/lorem" />

        <TextView
            android:id="@+id/product_item_price"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            tools:text="@tools:sample/us_zipcodes" />

        <ImageView
            android:id="@+id/product_item_image"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:contentDescription="@string/product_image"
            android:scaleType="fitCenter"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/product_item_detail_flow"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintWidth_percent=".33"
            tools:srcCompat="@tools:sample/avatars" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</com.google.android.material.card.MaterialCardView>

Consider another flow like this with multiple views that putting a divider after each item is not wise in my opinion:

enter image description here

So in short how can I create a divider item decoration for constraint layout's flow children?

Edit: both of these flows are actually item for a recyclerview

Upvotes: 2

Views: 934

Answers (1)

Yamin Siahmargooei
Yamin Siahmargooei

Reputation: 3707

I didn't find a way to achieve this using ConstraintLayout and Flow, however, this can be achieved using FlexboxLayout. Because FlexboxLayout has a dividerDrawable attribute that automatically puts a divider between child views.

After adding the FlexboxLayout library to your app/module you can use it like this:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.flexbox.FlexboxLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:alignItems="stretch"
        app:dividerDrawable="@drawable/flex_divider"
        app:flexDirection="column"
        app:showDivider="middle">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            tools:layout_editor_absoluteX="63dp" />

        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            tools:layout_editor_absoluteX="126dp" />

    </com.google.android.flexbox.FlexboxLayout>

</FrameLayout>

and for @drawable/flex_divider create this:

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size
        android:width="2dp"
        android:height="2dp" />
    <solid android:color="?colorPrimaryDark" />
</shape>

This ultimately results in: flexbox

Upvotes: 1

Related Questions