Java中的Android淡入淡出动画

170

我想要一个ImageView的2秒动画,其中包括1000毫秒的淡入和1000毫秒的淡出。

这是我在ImageView构造函数中的目前代码:

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setDuration(1000);

Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);

AnimationSet animation = new AnimationSet(true);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);

当我运行这个动画时,没有任何东西显示出来。但是,当我移除其中一个alpha动画时,行为表现如预期。

我已经尝试过的事情:

  • 使用每种可以想象的setFillBeforesetFillAftersetFillEnabled的组合。
  • AnimationSet添加LinearInterpolator

1
是的,您可以淡入淡出图像!这个教程应该能解决问题。http://sankarganesh-info-exchange.blogspot.com/2011/04/performing-animation-in-android.html - Adam Storm
该教程描述了使用XML的方法。你知道如何使用Java实现相同的事情吗? - plowman
好的,我现在不在我的编程电脑旁边,所以无法测试这段代码,但是你可以在Java中设置XML属性。这是原始代码:android:interpolator="@android:anim/accelerate_interpolator" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> 因此,你可能可以使用MyTween.setDurationg(300) MyTween.fromAlpha(0.0) MyTween(1.0)。 - Adam Storm
13个回答

291

我自己解决了问题。解决方案最终基于插值器。

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); //add this
fadeIn.setDuration(1000);

Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); //and this
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);

AnimationSet animation = new AnimationSet(false); //change to false
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);
如果你正在使用 Kotlin
val fadeIn = AlphaAnimation(0f, 1f)
fadeIn.interpolator = DecelerateInterpolator() //add this
fadeIn.duration = 1000

val fadeOut = AlphaAnimation(1f, 0f)
fadeOut.interpolator = AccelerateInterpolator() //and this
fadeOut.startOffset = 1000
fadeOut.duration = 1000

val animation = AnimationSet(false) //change to false
animation.addAnimation(fadeIn)
animation.addAnimation(fadeOut)
this.setAnimation(animation)

1
如果您想进行5或6次淡入/淡出,每次都有非常小的延迟,如每次100毫秒,您是否可以使用类似于这样的东西?我尝试过,但不是很流畅。目的是模拟例如灯泡无法正常工作并闪烁的情况。 - Chayy
尝试在循环中调用this.setAnimation。 - Jono
我曾考虑过淡出上一个背景图像并淡入当前的背景图像,但这个答案启发了我,我只需要淡入当前的背景图像并淡出当前的背景图像,因为AlphaAnimation无法淡入/淡出两个不同的图像。 - macio.Jun
9
我认为你不需要有两个独立的动画... 我认为你可以只用一个动画,然后设置参数:fadeInOut.setRepeatMode(Animation.REVERSE); - RoundSparrow hilltx
其次:如果你想重复执行,无需像@jonney所说的那样调用循环。使用fadeInOut.setRepeatCount(6)——将6更改为您希望重复的次数即可。让Android中的本地C++代码处理所有这些工作比调用Java循环要轻量得多。 - RoundSparrow hilltx
显示剩余2条评论

166

我知道这个问题已经有答案了,但是......

<?xml version="1.0" encoding="utf-8"?> 
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1.0" 
    android:toAlpha="0.0" 
    android:duration="1000"    
    android:repeatCount="infinite" 
    android:repeatMode="reverse"
    />

这是一种快速且简单的方法,可以进行自我重复的淡入和淡出。享受吧。

编辑: 在您的活动中添加以下内容:

yourView.startAnimation(AnimationUtils.loadAnimation(co‌​ntext, R.anim.yourAnimation));

8
+1是因为有了这个答案,我能够制作一个淡入、淡出和淡入的序列(只需设置repeatCount="2")。我无法像被接受的答案建议的那样连接动画。 - ElYeante
1
声明了这个 alpha 资源后,我该如何使用它?谢谢。 - zozelfelfo
1
zozelfelfo 这只是一个动画 XML,因此将其加载到代码中,然后在您想要影响的任何视图上调用 startAnimation。 - Konrad Winkowski
@KonradWinkowski的startAnimation方法需要一个动画对象作为参数!我应该传递什么? - Ahmad Vatani
对于那些寻求更完整答案的人:viewToAnimate.startAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in_out),其中在res文件夹下的anim文件夹中有一个fade_in_out.xml文件。 - Chris Knight

39
viewToAnimate.animate().alpha(1).setDuration(1000).setInterpolator(new DecelerateInterpolator()).withEndAction(new Runnable() {
    @Override
    public void run() {
        viewToAnimate.animate().alpha(0).setDuration(1000).setInterpolator(new AccelerateInterpolator()).start();
    }
}).start();

4
Elegante适用于Marshmallow! - Eddie
1
需要注意的重要一点是,如果您在第二个动画中使用setStartDelay()来延迟其启动,则需要将其重置为0以在第一个动画中使用。否则它将记住该延迟以用于任何后续动画。 - zkon

28

这是我的解决方案,使用AnimatorSet,它似乎比AnimationSet更加可靠。

// Custom animation on image
ImageView myView = (ImageView)splashDialog.findViewById(R.id.splashscreenImage);

ObjectAnimator fadeOut = ObjectAnimator.ofFloat(myView, "alpha",  1f, .3f);
fadeOut.setDuration(2000);
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(myView, "alpha", .3f, 1f);
fadeIn.setDuration(2000);

final AnimatorSet mAnimationSet = new AnimatorSet();

mAnimationSet.play(fadeIn).after(fadeOut);

mAnimationSet.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        mAnimationSet.start();
    }
});
mAnimationSet.start();

1
我不得不使用ObjectAnimator而不是Animation来获得一个可行的解决方案,因为出于某种原因,每当我启动AlphaAnimation时,它都会运行两次并产生一些奇怪的闪烁。 - Andrew Orobator
优雅的解决方案 - Vlad
好的,现在可能有点晚了,但我认为这可能会有所帮助。在再次在同一视图上使用它之前,请清除动画。 - Bhavesh Moradiya

24

另一种选择:

不需要为fadeInfadeOut定义两个动画。 fadeOutfadeIn的反向。

因此,您可以使用Animation.REVERSE来执行此操作,如下所示:

AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(1000);
alphaAnimation.setRepeatCount(1);
alphaAnimation.setRepeatMode(Animation.REVERSE);
view.findViewById(R.id.imageview_logo).startAnimation(alphaAnimation);

onAnimationEnd 事件发生时:

alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
    @Override
        public void onAnimationStart(Animation animation) {
            //TODO: Run when animation start
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            //TODO: Run when animation end
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            //TODO: Run when animation repeat
        }
    });

17

因为我相信 XML 的强大(用于布局),所以这是被接受的 答案 的对应项,但它纯粹作为一种动画资源:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:fillAfter="true">
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="1000" />
    <alpha
        android:fromAlpha="1"
        android:toAlpha="0"
        android:duration="1000"
        android:startOffset="1000"/>
</set>

fillAfter属性用于让渐变在动画完成后保持。interpolator用于处理动画的插值器,如其名称所示。您还可以使用其他类型的插值器,例如线性或过冲。

确保在视图上开始您的动画:

yourView.startAnimation(AnimationUtils.loadAnimation(co‌​ntext, R.anim.fade));

@KGCybeX 没问题,很高兴能帮到你 :) - DarkCygnus
1
非常有用且简洁。对我来说完美地运作。 - Fernando Barbosa

11

这是我用来淡入/淡出视图的方法,希望能对某些人有所帮助。

private void crossFadeAnimation(final View fadeInTarget, final View fadeOutTarget, long duration){
    AnimatorSet mAnimationSet = new AnimatorSet();
    ObjectAnimator fadeOut = ObjectAnimator.ofFloat(fadeOutTarget, View.ALPHA,  1f, 0f);
    fadeOut.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            fadeOutTarget.setVisibility(View.GONE);
        }

        @Override
        public void onAnimationCancel(Animator animation) {
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }
    });
    fadeOut.setInterpolator(new LinearInterpolator());

    ObjectAnimator fadeIn = ObjectAnimator.ofFloat(fadeInTarget, View.ALPHA, 0f, 1f);
    fadeIn.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            fadeInTarget.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animator animation) {}

        @Override
        public void onAnimationCancel(Animator animation) {}

        @Override
        public void onAnimationRepeat(Animator animation) {}
    });
    fadeIn.setInterpolator(new LinearInterpolator());
    mAnimationSet.setDuration(duration);
    mAnimationSet.playTogether(fadeOut, fadeIn);
    mAnimationSet.start();
}

不知何故,这是唯一一个包括设置可见性的答案,很好。 - Luke Needham

11
如果你使用Animator来制作动画,你可以:

anim (目录) -> fade_out.xml

<?xml version="1.0" encoding="UTF-8"?>
<objectAnimator
    android:propertyName="alpha"
    android:valueFrom="0"
    android:valueTo="1"
    xmlns:android="http://schemas.android.com/apk/res/android"/>

在Java中
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.fade_out);
animator.setTarget(the_view_you_want_to_animation);
animator.setDuration(1000);
animator.start();

只使用Java代码让动画淡出的另一种方式是:
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(the_view_you_want_to_animation, "alpha",  1f, 0);
fadeOut.setDuration(2000);
fadeOut.start();

在目录anim*中,不是animator。 - LeTadas
@LeTadas 在 Animator 目录下,根据 Android Studio 进行操作。 - Pat Lee
android:duration="1000" - Pat Lee

10

动画集似乎根本不能按预期工作。最后我放弃了,并使用Handler类的postDelayed()方法来顺序执行动画。


4
您可以使用animationListener,像这样:
您还可以使用animationListener,如下所示:
fadeIn.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation animation) {
        this.startAnimation(fadeout);
    }
});

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