androidandroid-layoutandroid-constraintlayoutflowlayout

how to get flow layout's row count in android


I have 3 views that i included in flow helper of constraint layout and are laid out like this:

|TextView1| |View(delimiter)| |TextView2|

when text of TextView2 doesn't fit, it moves to next line:

|TextView1| |View(delimiter)| |TextView2|

the problem here is that when TextView2 moves to next line i need to remove or make View(delimiter) visibility as gone, and to do so i need a way to know if flow layout has more than one row.

i tried to look for built-in functions inside flow helper but found nothing.


Solution

  • Currently there is no method to get the Flow Layout row count but you can achieve this kind of effect by creating a subclass of androidx.constraintlayout.helper.widget.Flow and override the function fun updatePostLayout(container: ConstraintLayout) which is used when you want to update its internal object post layout or set up connections for the pointed elements. In this method you can have your custom logics to change the visibility of the View(delimiter) accordingly. Below is an example of the CustomFlow subclass:

    class CustomFlow : Flow {
    
        constructor(context: Context?) : super(context) {}
        constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {}
        constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
    
        override fun updatePreLayout(container: ConstraintLayout) {
            super.updatePreLayout(container)
        }
    
        override fun updatePostLayout(container: ConstraintLayout) {
            super.updatePostLayout(container)
    
            val tv1 = container.getViewById(R.id.textView1) as TextView
            val delView = container.getViewById(R.id.delimiterView) as View
            val tv2 = container.getViewById(R.id.textView2) as TextView
    
            if (tv2.top != tv1.top || tv2.lineCount > 1) {
                delView.visibility = GONE
            } else {
                delView.visibility = VISIBLE
            }
        }
    }
    

    And can be used in your xml like below:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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">
    
        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="[TEXTVIEW 1 TEXT]"
            tools:ignore="MissingConstraints" />
    
        <View
            android:id="@+id/delimiterView"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="@android:color/holo_green_light"
            tools:ignore="MissingConstraints" />
    
        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="[TEXTVIEW 2 TEXT]"
            tools:ignore="MissingConstraints" />
    
        <com.mypackage.name.CustomFlow
            android:id="@+id/flow"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:padding="10dp"
            app:constraint_referenced_ids="textView1,delimiterView,textView2"
            app:flow_horizontalBias="0"
            app:flow_horizontalGap="10dp"
            app:flow_horizontalStyle="packed"
            app:flow_verticalBias="0"
            app:flow_wrapMode="chain"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    Result when TextView2 is short (View-delimiter is visible):

    small_text

    Result when TextView2 is long and goes to the next line (View-delimiter is gone):

    long_text