Search code examples
androidkotlinandroid-layoutandroid-constraintlayout

How to set (programatically) Gone Margin in Constraint Layout?


There is a use case where 4 views are connected vertically (named "A","B","C","D" respectively from top to bottom).

            <include
                android:id="@+id/A"
                layout="@layout/search_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/dimen_16dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_title" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/B"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="12dp"
                android:layout_marginTop="12dp"
                android:nestedScrollingEnabled="false"
                android:visibility="gone"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/A"
                tools:itemCount="3"
                tools:listitem="@layout/item_layout"
                tools:visibility="visible" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/C"
                android:layout_width="@dimen/dimen_0dp"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="@dimen/dimen_16dp"
                android:layout_marginTop="12dp"
                android:drawableStart="@drawable/ic"
                android:drawablePadding="@dimen/dimen_6dp"
                android:fontFamily="@string/font_family_roboto_regular"
                android:text="@string/pb_tag_error_note"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/B"
                tools:visibility="visible" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/D"
                android:layout_width="@dimen/dimen_0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/dimen_16dp"
                android:background="#11101010"
                android:fontFamily="@string/font_family_roboto_medium"
                android:paddingHorizontal="@dimen/dimen_16dp"
                android:paddingVertical="6dp"
                android:text="@string/text"
                android:textColor="@color/black"
                android:textSize="14sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/C"
                app:layout_goneMarginTop="@dimen/dimen_12dp"
                tools:visibility="visible" />

When C is not visible then gone margin is set to 12dp resulting in a height of 16dp (12dp + 4dp RV item margin) from "B". But when both "B" & "C" are gone then the gap between "A" & "D" is needed to be 24dp.

The approach I'm using right now is programatically attaching D to the bottom of A & making margin as 24dp. Is there a way by which I can set gone margin top of D as 24dp when both B & C are gone?


Solution

  • You can make use of a Space widget as follows:

    • Place a space widget into the layout that is constrained to the parent start and the bottom of "A". The height of the widget will be 12dp. Name this widget space.
    • Create a Barrier widget with a direction as bottom and the referenced ids as space,C.
    • Constraint the top of "D" to the barrier.

    You may need to make a few other adjustment.

    The idea is that the Space widget will reserve 12dp of space below "A" but not add anything that is visible. "D" will float up as widgets disappear with 12dp margin until it hits the Space. At that point it will have 12dp top margin plus the height of the Space (12dp) which is 24dp.

    Here is an example layout:

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="16dp">
    
        <TextView
            android:id="@+id/A"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_blue_light"
            android:gravity="center_horizontal"
            android:text="A"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <Space
            android:id="@+id/space"
            android:layout_width="wrap_content"
            android:layout_height="12dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/A" />
    
        <TextView
            android:id="@+id/B"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:background="@android:color/holo_blue_light"
            android:gravity="center_horizontal"
            android:text="B"
            android:visibility="gone"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/A" />
    
        <TextView
            android:id="@+id/C"
            android:layout_width="@dimen/dimen_0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:background="@android:color/holo_blue_light"
            android:gravity="center_horizontal"
            android:text="C"
            android:visibility="gone"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/B"
            app:layout_goneMarginTop="12dp" />
    
        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierAllowsGoneWidgets="true"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="space,C" />
    
        <TextView
            android:id="@+id/D"
            android:layout_width="@dimen/dimen_0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:background="@android:color/holo_blue_light"
            android:gravity="center_horizontal"
            android:text="D"
            android:textColor="@color/black"
            android:textSize="14sp"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/barrier" />
    </androidx.constraintlayout.widget.ConstraintLayout>