Agung
Agung

Reputation: 13853

how to set constraint to different view if certain view visibility is gone in constraint layout?

I have two different toolbars in my main activity. I only show one toolbar at a time. if one toolbar visibility is visible, the other will be gone. it is controlled by if else statement

the two toolbar is called:

those two have different height.

I am using include to attach the toolbar in my main activity.

here is the xml of my main activity

<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".Activities.MainActivity" android:id="@+id/constraintLayout_main_activity">


    <include
            android:id="@+id/include_toolbar_general"
            layout="@layout/include_toolbar_general"
            android:visibility="visible"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" android:layout_width="0dp"
            android:layout_height="wrap_content"/>

    <include
            android:id="@+id/include_toolbar_search"
            layout="@layout/include_toolbar_search"
            android:visibility="gone"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" android:layout_width="0dp"
            android:layout_height="wrap_content"/>


    <fragment
            android:id="@+id/nav_host_fragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toTopOf="@+id/bottom_nav"
            app:layout_constraintTop_toBottomOf="@+id/include_toolbar_general"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:name="androidx.navigation.fragment.NavHostFragment"
            app:navGraph="@navigation/main_graph"
            app:defaultNavHost="true"/>


</androidx.constraintlayout.widget.ConstraintLayout>

as you can see, include_toolbar_general is initially visible. and the fragment below it has constraintTop_toBottomOf to include_toolbar_general

the problem is, when in certain condition, the include_toolbar_general will be gone. and the fragment will go up and it seems overlap the include_toolbar_search (that visible, if general toolbar is gone).

i want to make, when include_toolbar_general visibility is gone, then the fragment below it will have constraintTop_toBottomOf include_toolbar_search

how to do that ?

Upvotes: 11

Views: 6572

Answers (2)

Cheticamp
Cheticamp

Reputation: 62841

In your design, you have two toolbars only one of which is visible at any given time; the other is gone. A fragment below the toolbar should be be constrained to the bottom of the toolbar that is showing. Here is one way to do this without introducing additional complexity or views. Take a look at Visibility Behavior in the documentation for reference.

Below is a layout that mimics your layout with TextViews instead of includes for simplicity, but the concepts will work for your included files. Each TextView has its top constrained to the view above.

<androidx.constraintlayout.widget.ConstraintLayout 
    android:id="@+id/constraintLayout_main_activity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_green_light"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/include_toolbar_general"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="@android:color/holo_blue_bright"
        android:gravity="center"
        android:text="include_toolbar_general"
        android:textAppearance="@style/TextAppearance.AppCompat.Display1"
        android:visibility="visible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/include_toolbar_search"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="include_toolbar_search"
        android:textAppearance="@style/TextAppearance.AppCompat.Display1"
        android:visibility="visible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/include_toolbar_general" />


    <TextView
        android:id="@+id/nav_host_fragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_orange_light"
        android:gravity="center_horizontal"
        android:text="nav_host_fragment"
        android:textAppearance="@style/TextAppearance.AppCompat.Display1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/include_toolbar_search" />

</androidx.constraintlayout.widget.ConstraintLayout>

In the following video, the TextViews that represent your included layout are alternated set to gone. As you can see, the fragment responds by setting its top to the bottom of the view that is visible.

enter image description here

Upvotes: 4

Pawel Laskowski
Pawel Laskowski

Reputation: 6346

You can set a Barrier to be aligned with the bottom of whichever toolbar is currently showing and constrain the top of the Fragment to that Barrier:

<androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="include_toolbar_general,include_toolbar_search" />

And in your <fragment> change:

app:layout_constraintTop_toBottomOf="@+id/include_toolbar_general"

to:

app:layout_constraintTop_toBottomOf="@+id/barrier"

Upvotes: 14

Related Questions