Marquee behavior in TextView: Android

What we are going to achieve is Marquee’s behavior using animation.

Now let’s see how we can achieve this.

Firstly we need two textView inside a frame layout, both having the same text (will be discussed later). For the above design, I will write like this:-

<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/bt_animate_text"
android:layout_centerInParent="true"
android:layout_marginLeft="8dp"
android:layout_marginEnd="76dp"
android:layout_marginRight="76dp"
android:layout_marginBottom="32dp"
android:layout_marginStart="8dp">
<TextView
android:id="@+id/tv_actual_text"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="24dp"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:text="Animating text"/>
<TextView
android:id="@+id/tv_dummy_text"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="24dp"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:text="Animating text"/>
</FrameLayout>

Here I have used hardcode strings for testing, please feel free to use resource file String.xml for that. Here both TextViews are identical. We will see their significance below.

For animating text like this, which you have seen in many short videos app, we are going to use Value Animator, which was added in API level 11.

val animator = ValueAnimator.ofFloat(1.0f, 0.0f).apply {
this.repeatCount = ValueAnimator.INFINITE
this.interpolator = LinearInterpolator()
this.duration = 6000L
this.addUpdateListener { animation ->
val progress = animation.animatedValue as Float
val width = tv_actual_text.width.toFloat()
val translationX = width * progress
tv_actual_text.translationX = translationX - width
tv_dummy_text.translationX = translationX
}
}

We are using repeactCount, interpolator, duration, and one listener here. Let’s see the significance of each one:

  1. repeatCount:- will determine how many times to repeat the text; we have used ValueAnimator.INFINITE for infinite animation, you can give it an int value how many times you want to repeat it.
  2. Interpolator:- will determine whether the animation runs with linear or non-linear motion. You can try CycleInterpolator, OvershootInterpolator, etc. and see what happens to your text 😂.
  3. Duration:- represents the length of the animation. The default duration is 300 milliseconds. It decides the speed of the animation. If we reduce this, our text will animate fast vice-versa.
  4. updateListener:- the last one is the update listener, which returns the animation object. Here goes the logic of the whole animation, what we are doing here we are calculating the width of the first TextView and translating the x-axis of actual text view as well as of dummy text view. So what’s happening here is, as actual Textview moves to left, we calculate how much it has moved to show the dummy Textview from the right side accordingly.

Now everything is set, so let’s see how to start the animation. It’s straightforward, use

animator.start()