如何制作类似WhatsApp通话界面的动画?

3

我正在尝试编写类似于WhatsApp通话屏幕的动画。但是我不知道实现这一点的正确方法。

Whatsapp Animation

为了实现这个动画,我开始尝试使用淡入淡出动画。以下是我的淡入淡出动画设置方法:

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;
}

对于每一个动画,animationlisteners的onAnimationEnd方法会触发动画重新开始。fadeIn动画启动fadeOut动画,而fadeOut动画启动fadeIn动画。

    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");
        }
    });

初始化

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);

我正在尝试使用淡出效果来为每个按钮添加动画,但它并没有按照我的预期工作。我该如何实现类似 WhatsApp 的动画效果?
right1.startAnimation(right1FadeOut);
right2.startAnimation(right2FadeOut);          
right3.startAnimation(right3FadeOut);

这是结果。

MyAnimation

3个回答

2
我建议您使用Animator对象而不是Animation,然后可以使用AnimatorSet来将所有动画器作为一个组进行控制(即:顺序)。
例如:
活动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>

活动类:

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
    }
}

0

尝试在您的AnimationListeneronAnimationStart方法中使用递增延迟来启动后续动画。

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 )
            {

            }
        } );

还有你喜欢的动画效果

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 );

当您重新开始时,您可能需要进行一些微调,但这样做可以使它们同步。只需使用第一个fadeIn动画开始即可。

arrow1.startAnimation( arrow1FadeIn );

0

我建议您使用Facebook Rebound库

它支持像Facebook一样的Spring动画。它还有一个很酷的功能叫做SpringChain,可以自动播放一系列从开始到结束使用Spring物理学的动画序列。您可以自定义如何对视图进行动画处理(缩放、透明度、平移等)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接