2

I'm using a TextSwitcher to animate the text changes. I'm using a slide up animation when the text is changed. However the text is not sliding up to the container. Have a look at the video posted below. The text is neither sliding in from the red border nor sliding out to the red order. How should i go about to achieve a behavior where the text slides in from the red border and slides out to the red border?

enter image description here

The layout looks like this:

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="top">

    <androidx.cardview.widget.CardView
        android:id="@+id/iv_background"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        app:cardCornerRadius="20dp"
        app:cardElevation="0dp"
        app:cardPreventCornerOverlap="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/iv_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            app:shapeAppearance="@style/ContainerShape" />

        <View
            android:id="@+id/border"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/border" />

    </androidx.cardview.widget.CardView>

    <TextSwitcher
        android:id="@+id/tv_textswitcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:inAnimation="@anim/slide_up_from_bottom"
        android:outAnimation="@anim/slide_up_to_top"
        android:visibility="visible"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="@+id/iv_background"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/iv_background"
        app:layout_constraintTop_toTopOf="@+id/iv_background"
        app:layout_constraintVertical_bias="1.0">

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/text_background"
            android:ellipsize="end"
            android:lineHeight="20dp"
            android:text="Text 1"
            android:paddingStart="12dp"
            android:paddingTop="8dp"
            android:paddingEnd="12dp"
            android:paddingBottom="8dp"
            android:textSize="14sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/text_background"
            android:ellipsize="end"
            android:lineHeight="20dp"
            android:paddingStart="12dp"
            android:paddingTop="8dp"
            android:paddingEnd="12dp"
            android:paddingBottom="8dp"
            android:textSize="14sp" />

    </TextSwitcher>

</androidx.constraintlayout.widget.ConstraintLayout>

Animation files:

slide_up_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="1000"
        android:fromYDelta="100%"
        android:toYDelta="0" />
</set>

slide_up_to_top.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <translate
        android:duration="1000"
        android:fromYDelta="0"
        android:toYDelta="-100%" />
</set>

text_background.xml

<shape android:shape="rectangle">
            <corners android:radius="18dp" />
            <solid android:color="#e8e8e8" />
        </shape>
div
  • 1,475
  • 3
  • 22
  • 32

2 Answers2

2

There are actually multiple issues which need to be fixed here.

  1. Remove the margin from TextSwitcher and set it to TextViews. As mentioned by @D.McDermott.
<TextSwitcher
        android:id="@+id/tv_textswitcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:inAnimation="@anim/slide_up_from_bottom"
        android:outAnimation="@anim/slide_up_to_top"
        android:visibility="visible"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="@+id/iv_background"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/iv_background"
        app:layout_constraintTop_toTopOf="@+id/iv_background"
        app:layout_constraintVertical_bias="1.0">

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:background="@drawable/text_background"
            android:ellipsize="end"
            android:lineHeight="20dp"
            android:paddingStart="12dp"
            android:paddingTop="8dp"
            android:paddingEnd="12dp"
            android:paddingBottom="8dp"
            android:text="Text 1"
            android:textSize="14sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:background="@drawable/text_background"
            android:ellipsize="end"
            android:lineHeight="20dp"
            android:paddingStart="12dp"
            android:paddingTop="8dp"
            android:paddingEnd="12dp"
            android:paddingBottom="8dp"
            android:textSize="14sp" />

    </TextSwitcher>
  1. The yDelta in animation should be with respect to the parent and not with respect to the view. So, we need to use 100%p instead of 100%.

slide_up_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="1000"
        android:fromYDelta="100%p"
        android:toYDelta="0" />
</set>

slide_up_to_top.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <translate
        android:duration="1000"
        android:fromYDelta="0"
        android:toYDelta="-100%p" />
</set>
  1. Put the red border above the textview in the layout hierarchy. This is very important as this will ensure that the textview disappears into the red border and doesn't go beyond it. So, i moved the border view to the bottom of the layout. Ideally, you can just give the border to your parent and not worry about putting this view at all. But i had some other usecase, so i had to do that.
<View
        android:id="@+id/border"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/border"
        app:layout_constraintBottom_toBottomOf="@+id/iv_background"
        app:layout_constraintEnd_toEndOf="@+id/iv_background"
        app:layout_constraintStart_toStartOf="@+id/iv_background"
        app:layout_constraintTop_toTopOf="@+id/iv_background" />

The complete layout looks like this now:

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="top">

    <androidx.cardview.widget.CardView
        android:id="@+id/iv_background"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        app:cardCornerRadius="20dp"
        app:cardElevation="0dp"
        app:cardPreventCornerOverlap="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/iv_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            app:shapeAppearance="@style/ContainerShape" />

    </androidx.cardview.widget.CardView>

    <TextSwitcher
        android:id="@+id/tv_textswitcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:inAnimation="@anim/slide_up_from_bottom"
        android:outAnimation="@anim/slide_up_to_top"
        android:visibility="visible"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="@+id/iv_background"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/iv_background"
        app:layout_constraintTop_toTopOf="@+id/iv_background"
        app:layout_constraintVertical_bias="1.0">

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:background="@drawable/text_background"
            android:ellipsize="end"
            android:lineHeight="20dp"
            android:paddingStart="12dp"
            android:paddingTop="8dp"
            android:paddingEnd="12dp"
            android:paddingBottom="8dp"
            android:text="Text 1"
            android:textSize="14sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:background="@drawable/text_background"
            android:ellipsize="end"
            android:lineHeight="20dp"
            android:paddingStart="12dp"
            android:paddingTop="8dp"
            android:paddingEnd="12dp"
            android:paddingBottom="8dp"
            android:textSize="14sp" />

    </TextSwitcher>

    <View
        android:id="@+id/border"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/border"
        app:layout_constraintBottom_toBottomOf="@+id/iv_background"
        app:layout_constraintEnd_toEndOf="@+id/iv_background"
        app:layout_constraintStart_toStartOf="@+id/iv_background"
        app:layout_constraintTop_toTopOf="@+id/iv_background" />

</androidx.constraintlayout.widget.ConstraintLayout>

And here's a GIF for the resulting animation:

enter image description here

div
  • 1,475
  • 3
  • 22
  • 32
1

Although the CardView and the TextSwitcher are constrained to the exact same positions, they aren’t the same size. The text switchers height (and width) is smaller due to the margin you set to it.

The solution would be to remove the margin from the TextSwitcher and set it to the TextViews instead. If this covers the red border you should set the background of the TextSwitcher to something transparent.

div
  • 1,475
  • 3
  • 22
  • 32
D. McDermott
  • 100
  • 7
  • Removing margins from textswitcher and adding it to the textviews instead doesn't fix the issue. However, there 's a noticeable change. The textview is now overlapping with the red border while sliding up or down. – div May 15 '20 at 04:09
  • Can you not just move it to delta -200% instead of -100%? – D. McDermott May 15 '20 at 07:53
  • It's better but not good enough. I also added a fade out/in effect. The problem is the text goes over the red border when it slides up. Still doesn't slides in from the red border and slides out to the red border. It's going beyond the red border. https://i.stack.imgur.com/aXCyy.gif – div May 15 '20 at 11:51
  • It was an issue with my layout. The translationZ of red border was lower than the translationZ of textview. – div May 15 '20 at 13:37
  • Meaning the Problem is completely fixed now? – D. McDermott May 15 '20 at 13:38
  • There were 3 issues: 1. The issue that you pointed out regarding margins. 2. Setting the delta to 100%p rather than 100%. 3. Putting the red border view at last in the layout so that it is above all other elements. – div May 15 '20 at 13:50