cauende
cauende

Reputation: 135

Animate View Visibility Pushing down Views Below

I am currently implementing a fairly simple login screen using a custom implementation of material's TextInputLayout. I am using a custom view to show field errors. The problem here is that when I set the view from GONE to VISIBLE, it moves the fields above and under it. I only want the views below to move down, and keep the views above in the same position.

I have tried using the ViewPropertyAnimator but this just animates the fading in and out of the error view.

errorView.visibility = View.VISIBLE
        errorView.animate()
            .alpha(1f)
            .setListener(null)
            .duration = 300
errorView.animate()
            .alpha(0.0f)
            .setDuration(300)
            .setListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    super.onAnimationEnd(animation)
                    errorView.visibility = View.GONE
                }
            })

In essence I would like the following to happen instead:

---------------------
| Email             |
---------------------  
                     <- Error to show here and move password field down
---------------------  |
| Password          |  v
---------------------


Result:
---------------------
| Email             |  <- Stay in same position
---------------------
----------------------
|Email must be valid | <- Error
----------------------

---------------------  |
| Password          |  v
---------------------

Below is an example of an XML layout to exemplify this. Note that this does not match my layout but still shows the same problem.

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_centerInParent="true">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"/>

        <TextView
            android:id="@+id/errorView"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:text="Email must be valid"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:visibility="gone"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"/>

        <Button
            android:id="@+id/login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:text="Login"/>
    </LinearLayout>

</RelativeLayout>

Upvotes: 1

Views: 1641

Answers (2)

Torhan Bartel
Torhan Bartel

Reputation: 560

Use XML Tag android:animateLayoutChanges="true" on parent layout.

Upvotes: 3

cauende
cauende

Reputation: 135

In my use case, all the child views are centred in a parent, thus making this impossible to achieve, because the parent pushes the child views (both up and down) in order to both create space for the error view, while keeping all the views centred.

The approach I chose instead is to specify a top margin to the email field, instead of centring the child views in the parent view.

This way, when the parent adds the error view - after visibility changes - it only pushes down all the views under the email field as intended.

Upvotes: 1

Related Questions