In this scenario we are going to make fade in – fade out animation in continuous mode, using the Android Animator class. Also it will be added some buttons to control the flow of the animation as the user wants. It is a simple example how fade in – out animation can be used.
First we need Main Activity class and its corresponding activity_main layout. In this case we are going to make the layout first and then, later, we are going to build the fade in / out animation implementation.
Activity Layout is like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:background="@color/colorPrimary" android:gravity="center" android:padding="20dp" android:text="@string/fadeInOutAnim" android:textColor="@color/white" android:textStyle="bold" android:visibility="invisible" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/startStopButton" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:text="@string/start" app:layout_constraintBottom_toTopOf="@id/pauseResumeButton" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> <Button android:id="@+id/pauseResumeButton" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginBottom="50dp" android:text="@string/pause" android:visibility="invisible" app:layout_constraintBottom_toTopOf="@id/signature" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/signature" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingBottom="10dp" android:text="@string/signature" android:textSize="12sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </android.support.constraint.ConstraintLayout> |
*As in the example, we use Constraint layout, which is useful when your app is displayed on different screen sizes.
Note that our fadeInOutText element and pauseResumeButton are set to be invisible. This will be explained further down in this example.
First we start off with declaring the Animator in our activity on a global class scope and setting the fade in / out time as a static variable in milliseconds. Ours is set to 1000L (long variable), but you can set as much as you want.
1 2 |
private Animator animator; private static final long ANIMATION_DURATION = 1000L; |
Then we need to add our views in the activity that we are going to use. These are the text view that we are going to animate, button for start/stop and button for pause/resume.
1 2 3 4 5 6 |
@BindView(R.id.fadeInOutText) TextView fadeInOutText; @BindView(R.id.startStopButton) Button startButton; @BindView(R.id.pauseResumeButton) Button pauseResumeButton; |
*We are using the ButterKnife library to bind the view`s from the layout in our activity class.
in onCreate metrhod we initialize the animator, assigning ObjectAnimator calling its static method ofFloat(); which takes view and float values so it knows whatĀ andĀ what is start and end pointĀ should be animated. so in ofFloat we have our viewĀ fadeInOutText, the property type which is View.ALPHA, and the float values 0f and 1f. This means that our view would be animated with alpha opacity 0 (invisible) and 1 (full visible), or from invisible to visible and vice versa.
1 2 3 4 5 6 7 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); animator = ObjectAnimator.ofFloat(fadeInOutText, View.ALPHA, 0f, 1f); } |
*Note that we use ButterKnife.bind(this); so it can BIND the views declared in the layout with our activity.
Next we need to set the buttons like this:
1 2 3 4 5 6 7 8 9 |
@OnClick(R.id.startStopButton) public void onStartClick() { // TODO implement click } @OnClick(R.id.pauseResumeButton) public void onPauseClick() { // TODO implement click } |
*On click annotation is provided by the ButterKnife library.
Start – Stop Button is implemented in specific way, that we use only one button for both starting and stopping the animation:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
if (animator != null) { if (!animator.isStarted()) { fadeInOutAnim(); startButton.setText(getString(R.string.stop)); pauseResumeButton.setVisibility(View.VISIBLE); } else { animator.end(); fadeInOutText.setVisibility(View.INVISIBLE); startButton.setText(getString(R.string.start)); pauseResumeButton.setVisibility(View.INVISIBLE); pauseResumeButton.setText(getString(R.string.pause)); } } |
First thing, we make sure that the animator is not null, and that we proceed to the next check if the animator is started. The isStarted() returns boolean value that tells us if the animation is started or not, and because the animator is not started and we have ! (NOT) operator the statement is true on first run (!(is started = false) and ! turns the boolean around thous is true), the IF block is executed. In this scope, we have fadeInOutAnim() method that is going to be described later, but just for now see it as the actual animation being called with it. The button is already set with text start. Why there is text setting “start” again? That is because when the start button is clicked the text changes to “stop”, so basically we need to set it back to “start “once the stop button is clicked. And here we come to the invisible element pauseResumeButton that we discussed earlier. When we click start button there is pause button with implementation that we need to elaborate later, and pause cannot be seen before the animation is started. if there is no animation going on, there is no need for pausing that is not there.
In the ELSE block, we add the logic of our stop button. There is animator.end() method that will end the animation. We set the text of the button to “start” once stop button is clicked. Also we set pause or resume button (depends on which is displayed) to be invisible. and set the default name “pause” for our pause / resume button.
1 2 3 4 5 6 7 8 9 10 11 12 |
@OnClick(R.id.pauseResumeButton) public void onPauseClick() { if (animator != null) { if (animator.isStarted() && !animator.isPaused()) { animator.pause(); pauseResumeButton.setText(getString(R.string.resume)); } else { animator.resume(); pauseResumeButton.setText(getString(R.string.pause)); } } } |
In our pause / resume button we implement the examples of pausing and resuming the animation. Basically the pause button do what is says it do, it pauses the animation in the moment we want, displaying the last state of the animation occurring on the display. With resume we continue to run it, from where it was paused. Similar logic is used in here as the start / stop button. If the animator is not null execute. If it is started and not paused, pause the animation and set the button text to “resume” else resume the animation and set the button text to “pause”.
Last, but most important part is the actual animation of the Text View:
1 2 3 4 5 6 7 |
private void fadeInOutAnim() { fadeInOutText.setVisibility(View.VISIBLE); animator.setDuration(ANIMATION_DURATION); ((ObjectAnimator) animator).setRepeatMode(ValueAnimator.REVERSE); ((ObjectAnimator) animator).setRepeatCount(ValueAnimator.INFINITE); animator.start(); } |
Here we set the invisible fadeInOutText element to be visible (so it can be animated) and add previously declared and initialized ANIMATION_DURATION to setDuratin() method on the animator that takes long as parameter. After that we set the repeat mode to be REVERSED (from transparent to full view) and how many times the animation should be repeated. If the repeat count is 0, the animation is never repeated. If the repeat count is greater than 0 orĀ INFINITE
, the repeat mode will be taken into account. The repeat count is 0 by default. In our case is set to INFINITE. And after everything is set, we start our animator.
You can get the whole project on GitHub BuktopMKD/fadeInOut
Hi would you mind letting me know which web host you’re working with?
I’ve loaded your blog in 3 completely different browsers and I must say this blog loads a lot
faster then most. Can you suggest a good web hosting provider at a fair
price? Kudos, I appreciate it!
Just want to say your article is as astounding.
The clarity in your post is just cool and i could assume you are an expert on this subject.
Well with your permission let me to grab your feed to keep up to date
with forthcoming post. Thanks a million and please keep up the enjoyable work.