简体   繁体   中英

How can I make animation like whatsapp call screen?

I am trying to write an animation like in WhatsApp Call screen. But I don't know what is the true way to achieve this.

Whatsapp动画

To achieve this animation I am starting trying with fadein and fadeout animation. These are my set methods for fade in and out animations.

private Animation setAnimFadeOut(int startOff,int duration){
    Animation animFadeOut;
    animFadeOut = new AlphaAnimation(1, 0);
    animFadeOut.setInterpolator(new AccelerateInterpolator());
    animFadeOut.setStartOffset(startOff);
    animFadeOut.setDuration(duration);
    return  animFadeOut;
}

private Animation setAnimFadeIn(int startOff,int duration){
    Animation animFadeIn;
    animFadeIn = new AlphaAnimation(0, 1);
    animFadeIn.setInterpolator(new AccelerateInterpolator());
    animFadeIn.setStartOffset(startOff);
    animFadeIn.setDuration(duration);
    return  animFadeIn;
}

and for every animations animationlisteners onAnimationEnd method triggers animation for restart. fadeIn animation starts fadeOut animation and fadeOut starts fadeIn animation.

    right1FadeOut.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationEnd(Animation animation) {
            right1.startAnimation(right1FadeIn);
            Log.i(TAG, "onAnimationEnd: 1 outEnd");
        }
    });
    right1FadeIn.setAnimationListener(new Animation.AnimationListener() {
        Override
        public void onAnimationEnd(Animation animation) {
            right1.startAnimation(right1FadeOut);
            Log.i(TAG, "onAnimationEnd: 1 inEnd");
        }
    });

Initialization

int startOff = 0;
int diff = 100;
int duration = 600;

final Animation right1FadeOut = setAnimFadeOut(startOff,duration);
final Animation right1FadeIn  = setAnimFadeIn(0,duration);
final Animation right2FadeOut = setAnimFadeOut(startOff+diff,duration+diff);
final Animation right2FadeIn  = setAnimFadeIn(0,duration);
final Animation right3FadeOut = setAnimFadeOut(startOff+diff*2,duration+diff*2);
final Animation right3FadeIn  = setAnimFadeIn(0,duration);

I am starting animation calling fadeout for every button and it did not work as I expected. How can I achieve animation like WhatsApp?

right1.startAnimation(right1FadeOut);
right2.startAnimation(right2FadeOut);          
right3.startAnimation(right3FadeOut);

this is the result.

MyAnimation

I would first use Animator objects instead of Animation, then i can use AnimatorSet to control all animators as a group. (aka: order)

For example:

activity XML:

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

    <TextView
        android:id="@+id/txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:focusable="true"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

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

        <ImageView
            android:id="@+id/img1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:alpha="0"
            android:src="@drawable/ic_launcher_foreground" />

        <ImageView
            android:id="@+id/img2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:alpha="0"
            android:src="@drawable/ic_launcher_foreground" />

        <ImageView
            android:id="@+id/img3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:alpha="0"
            android:src="@drawable/ic_launcher_foreground" />

        <ImageView
            android:id="@+id/img4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:alpha="0"
            android:src="@drawable/ic_launcher_foreground" />
    </LinearLayout>

</android.support.constraint.ConstraintLayout>

Activity Class:

Java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        View[] images = {findViewById(R.id.img1), findViewById(R.id.img2), findViewById(R.id.img3), findViewById(R.id.img4),}; //array of views that we want to animate

        //we will have 2 animator foreach view, fade in & fade out
        //prepare animators - creating array of animators & instantiating Object animators
        ArrayList<ObjectAnimator> anims = new ArrayList<>(images.length * 2);
        for (View v : images) anims.add(ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f).setDuration(80)); //fade in animator
        for (View v : images) anims.add(ObjectAnimator.ofFloat(v, View.ALPHA, 1f, 0f).setDuration(80)); //fade out animator

        final AnimatorSet set = new AnimatorSet(); //create Animator set object
        //if we want to repeat the animations then we set listener to start again in 'onAnimationEnd' method
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                set.start(); //repeat animator set indefinitely
            }
        });

        set.setStartDelay(600); //set delay every time we start the chain of animations

        for (int i = 0; i < anims.size() - 1; i++) set.play(anims.get(i)).before(anims.get(i + 1)); //put all animations in set by order (from first to last)

        findViewById(R.id.txt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { //start the animations on click
                set.start();
            }
        });
    }
}

Kotlin:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val images = arrayOf(img1, img2, img3, img4) //array of views that we want to animate

        //we will have 2 animator foreach view, fade in & fade out
        //prepare animators - creating array of animators & instantiating Object animators
        val anims = ArrayList<ObjectAnimator>(images.size * 2)
        for (v in images) anims.add(ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f).setDuration(80)) //fade in animator
        for (v in images) anims.add(ObjectAnimator.ofFloat(v, View.ALPHA, 1f, 0f).setDuration(80)) //fade out animator

        val set = AnimatorSet() //create Animator set object
        //if we want to repeat the animations then we set listener to start again in 'onAnimationEnd' method
        set.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator?) = set.start() //repeat animator set indefinitely
        })

        set.startDelay = 600 //set delay every time we start the chain of animations

        for (i in 0 until anims.size - 1) set.play(anims[i]).before(anims[i + 1]) //put all animations in set by order (from first to last)

        txt.setOnClickListener { set.start() } //start the animations on click
    }
}

Try to start your subsequent animations in your AnimationListener s onAnimationStart method with an increasing delay.

arrow1FadeIn.setAnimationListener( new Animation.AnimationListener() {
        @Override
        public void onAnimationStart( Animation animation )
        {
            arrow2.startAnimation( arrow2FadeIn );
        }

        @Override
        public void onAnimationEnd( Animation animation )
        {
            arrow1.startAnimation( arrow1FadeOut );
        }

            @Override
            public void onAnimationRepeat( Animation animation )
            {

            }
        } );
arrow1FadeOut.setAnimationListener( new Animation.AnimationListener()
        {
            @Override
            public void onAnimationStart( Animation animation )
            {
            }

            @Override
            public void onAnimationEnd( Animation animation )
            {
                arrow1.startAnimation( arrow1FadeIn );
            }

            @Override
            public void onAnimationRepeat( Animation animation )
            {

            }
        } );

And your animations like

final Animation arrow1FadeIn = setAnimFadeIn( startOff, duration );
final Animation arrow1FadeOut = setAnimFadeOut( startOff, duration );
final Animation arrow2FadeIn = setAnimFadeIn( diff, duration );
final Animation arrow2FadeOut = setAnimFadeOut( startOff, duration );
final Animation arrow3FadeIn = setAnimFadeIn( diff*2, duration );
final Animation arrow3FadeOut = setAnimFadeOut( startOff, duration );

You may need to twiddle a bit when starting all over again but this way, they should be in sync. Just start the first fadeIn Animation with

arrow1.startAnimation( arrow1FadeIn );

I suggest you use Facebook Rebound library .

It support Spring animation like facebook has. It also has cool feature called SpringChain , which automatically play a sequence of animation using Spring physics from start to end. You can custom how you want to animate the View (scale, alpha, translate ...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM