div
div

Reputation: 1533

Remove margin while switching text using textswitcher

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>

Upvotes: 3

Views: 290

Answers (2)

div
div

Reputation: 1533

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

Upvotes: 2

D. McDermott
D. McDermott

Reputation: 136

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.

Upvotes: 1

Related Questions