Conditional Positioning in Constraint Layout

Viewed 647

I have multiple views in a ConstraintLayout which may have their visibility set to GONE or VISIBLE depending on certain parts of a view model, like such:

    <ImageView
        android:id="@+id/logo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="@{viewModel.shouldShowLogo ? View.GONE : View.VISIBLE}"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/logo" />

This image will either show or disappear depending on state. Now I want to position another view, say, an EditText based on that same state, shouldShowLogo. If the logo is shown, I want to position the EditText below the logo, otherwise I want to position it below the top of the parent view (at the top of the screen, essentially). So far I've tried this:

    <EditText
        android:id="@+id/searchInput"
        android:layout_height="wrap_content"
        android:hint="@android:string/search_go"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@{viewModel.shouldShowLogo ? @id/logo : null}"
        app:layout_constraintTop_toTopOf="@{viewModel.shouldShowLogo ? null : ConstraintSet.PARENT_ID}"/>

This doesn't compile, I get the following error:

Cannot find a setter for <android.widget.EditText app:layout_constraintTop_toBottomOf> that accepts parameter type 'int'

Is this the proper way to achieve what I'm looking to do? I also get the feeling that I shouldn't be using ConstraintSet, but I'm honestly not sure.

TL;DR -- How can I sometimes constraint a view position based on another view when that other view is visible, and on the parent view when the other view is not visible?

1 Answers

Take a look at GONE margins. If your EditText is constrained top to bottom of the logo and the logo is constrained top to the top of the parent, then when the logo is GONE, the EditText will be constrained to the top of the parent. I think this is what you want.

Related