Android 使用 ImageView 淡入淡出
Posted
技术标签:
【中文标题】Android 使用 ImageView 淡入淡出【英文标题】:Android fade in and fade out with ImageView 【发布时间】:2012-01-04 00:29:12 【问题描述】:我在制作幻灯片时遇到了一些问题。
我在 xml 中创建了 2 个用于淡入和淡出的动画:
fadein.xml
<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:duration="2000"/>
</set>
fadeout.xml
<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:duration="2000"/>
</set>
我想做的是使用淡入淡出效果从 ImageView 更改图像,因此当前显示的图像将淡出,而另一个将淡入。 考虑到我已经设置了一个图像,我可以毫无问题地淡出这个图像:
Animation fadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.your_fade_in_anim);
imageView.startAnimation(fadeoutAnim);
然后,我设置了要显示的下一张图片:
imageView.setImageBitmap(secondImage);
它只是显示在 imageView 中,当我设置动画时它会隐藏图像,淡入淡出...有什么办法可以解决这个问题,我的意思是,当我这样做 imageView.setImageBitmap( secondImage); 命令,图像不会立即显示,只有在执行淡入动画时才显示?
【问题讨论】:
【参考方案1】:我想实现与您相同的目标,因此我编写了以下方法,如果您将 ImageView 和对图像可绘制对象的引用列表传递给它,该方法正是如此。
ImageView demoImage = (ImageView) findViewById(R.id.DemoImage);
int imagesToShow[] = R.drawable.image1, R.drawable.image2,R.drawable.image3 ;
animate(demoImage, imagesToShow, 0,false);
private void animate(final ImageView imageView, final int images[], final int imageIndex, final boolean forever)
//imageView <-- The View which displays the images
//images[] <-- Holds R references to the images to display
//imageIndex <-- index of the first image to show in images[]
//forever <-- If equals true then after the last image it starts all over again with the first image resulting in an infinite loop. You have been warned.
int fadeInDuration = 500; // Configure time values here
int timeBetween = 3000;
int fadeOutDuration = 1000;
imageView.setVisibility(View.INVISIBLE); //Visible or invisible by default - this will apply when the animation ends
imageView.setImageResource(images[imageIndex]);
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); // add this
fadeIn.setDuration(fadeInDuration);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); // and this
fadeOut.setStartOffset(fadeInDuration + timeBetween);
fadeOut.setDuration(fadeOutDuration);
AnimationSet animation = new AnimationSet(false); // change to false
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
animation.setRepeatCount(1);
imageView.setAnimation(animation);
animation.setAnimationListener(new AnimationListener()
public void onAnimationEnd(Animation animation)
if (images.length - 1 > imageIndex)
animate(imageView, images, imageIndex + 1,forever); //Calls itself until it gets to the end of the array
else
if (forever)
animate(imageView, images, 0,forever); //Calls itself to start the animation all over again in a loop if forever = true
public void onAnimationRepeat(Animation animation)
// TODO Auto-generated method stub
public void onAnimationStart(Animation animation)
// TODO Auto-generated method stub
);
【讨论】:
为了展示如何在代码中定义淡入淡出动画,先生,请给我投票 您还可以计算重复次数并在 onAnimationRepeat 方法中执行 Array.lenght%count @Crocodile 您认为您的代码中可能存在内存问题。让带有上述代码的活动继续运行。它将创建如此多的 AnimationSet 对象。一段时间后它是否有可能因 outOfMemory 而崩溃? 你先生是救命恩人! @Gem - 为什么特定的分配会导致问题?每次调用 imageView.setAnimation(animation) 时,对前一个动画的任何引用都会丢失,因此垃圾收集器将能够删除这个前一个对象。 AFAIK,不是内存问题。【参考方案2】:要按照您开始的方式实现这一点,您需要添加一个AnimationListener,以便您可以检测动画的开始和结束。当调用淡出的 onAnimationEnd() 时,您可以将 ImageView 对象的可见性设置为 View.INVISIBLE,切换图像并开始淡入动画 - 这里也需要另一个 AnimationListener。当您收到 onAnimationEnd() 用于淡入动画时,将 ImageView 设置为 View.VISIBLE,这应该会给您想要的效果。
我之前实现过类似的效果,但我使用了带有 2 个 ImageView 而不是单个 ImageView 的 ViewSwitcher。您可以使用淡入和淡出设置 ViewSwitcher 的“入”和“出”动画,以便它可以管理 AnimationListener 实现。然后您需要做的就是在 2 个 ImageView 之间交替。
编辑: 为了更有用,这里有一个如何使用 ViewSwitcher 的快速示例。我在https://github.com/aldryd/imageswitcher 包含了完整的源代码。
activity_main.xml
<ViewSwitcher
android:id="@+id/switcher"
android:layout_
android:layout_
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:inAnimation="@anim/fade_in"
android:outAnimation="@anim/fade_out" >
<ImageView
android:layout_
android:layout_
android:scaleType="fitCenter"
android:src="@drawable/sunset" />
<ImageView
android:layout_
android:layout_
android:scaleType="fitCenter"
android:src="@drawable/clouds" />
</ViewSwitcher>
MainActivity.java
// Let the ViewSwitcher do the animation listening for you
((ViewSwitcher) findViewById(R.id.switcher)).setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
ViewSwitcher switcher = (ViewSwitcher) v;
if (switcher.getDisplayedChild() == 0)
switcher.showNext();
else
switcher.showPrevious();
);
【讨论】:
谢谢你!我忘记了 serVisible!感谢 ViewSwitcher 的提示,这似乎比自己处理所有事情要容易。 @Aldryd 这在性能方面是否更有效?与所选答案相比(单独的 XML 文件)? @Ron 我并没有真正比较不同方法的性能。与为 ImageView 对象解码/使用位图相比,我认为使用 ViewSwitcher 与自己实现 AnimationListener 不会很明显。我最近发现如果你使用 API 11 或更高版本,你可以使用一些新的动画类。您可以在此处查看使用 API 11 交叉淡入淡出 2 个视图的示例:developer.android.com/training/animation/crossfade.html【参考方案3】:您是否考虑过使用 TransitionDrawable 代替自定义动画? https://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html
实现您正在寻找的一种方法是:
// create the transition layers
Drawable[] layers = new Drawable[2];
layers[0] = new BitmapDrawable(getResources(), firstBitmap);
layers[1] = new BitmapDrawable(getResources(), secondBitmap);
TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
imageView.setImageDrawable(transitionDrawable);
transitionDrawable.startTransition(FADE_DURATION);
【讨论】:
这是这个问题的最佳答案。 很抱歉碰到了问题,但如果我在处理程序中使用它,并将其置于永久循环中,则应用程序会在我拥有的其他恒定淡入/淡出动画中失去性能。有什么推荐吗? TransitionDrawable 只能处理两个图像/层。 Transition drawable 在运行 espresso 测试时导致 AppNotIdleException【参考方案4】:我使用了淡入淡出动画来替换旧图像的新图像
ObjectAnimator.ofFloat(imageView, View.ALPHA, 0.2f, 1.0f).setDuration(1000).start();
【讨论】:
查看android-developers.blogspot.com/2011/05/… 以获得更简洁的代码。 谢谢!!仍然相关...我现在最需要的! 谢谢!!这是最好的答案……实施起来非常简单,而且运行顺畅。【参考方案5】:基于 Aladin Q 的解决方案,这是我编写的一个辅助函数,它会在运行一点点淡出/淡入动画的同时更改 imageview 中的图像:
public static void ImageViewAnimatedChange(Context c, final ImageView v, final Bitmap new_image)
final Animation anim_out = AnimationUtils.loadAnimation(c, android.R.anim.fade_out);
final Animation anim_in = AnimationUtils.loadAnimation(c, android.R.anim.fade_in);
anim_out.setAnimationListener(new AnimationListener()
@Override public void onAnimationStart(Animation animation)
@Override public void onAnimationRepeat(Animation animation)
@Override public void onAnimationEnd(Animation animation)
v.setImageBitmap(new_image);
anim_in.setAnimationListener(new AnimationListener()
@Override public void onAnimationStart(Animation animation)
@Override public void onAnimationRepeat(Animation animation)
@Override public void onAnimationEnd(Animation animation)
);
v.startAnimation(anim_in);
);
v.startAnimation(anim_out);
【讨论】:
【参考方案6】:你可以通过两个简单的点来改变你的代码
1.在项目的anim文件夹中的xml中,设置淡入淡出持续时间不相等
2.在你的java类中,在淡出动画开始之前,设置第二个imageView可见性消失,然后在淡出动画开始后设置你想要淡入可见的第二个imageView可见性
淡出.xml
<alpha
android:duration="4000"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
fadein.xml
<alpha
android:duration="6000"
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
在你的java类中
Animation animFadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
ImageView iv = (ImageView) findViewById(R.id.imageView1);
ImageView iv2 = (ImageView) findViewById(R.id.imageView2);
iv.setVisibility(View.VISIBLE);
iv2.setVisibility(View.GONE);
animFadeOut.reset();
iv.clearAnimation();
iv.startAnimation(animFadeOut);
Animation animFadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
iv2.setVisibility(View.VISIBLE);
animFadeIn.reset();
iv2.clearAnimation();
iv2.startAnimation(animFadeIn);
【讨论】:
【参考方案7】:无限淡入淡出
AlphaAnimation fadeIn=new AlphaAnimation(0,1);
AlphaAnimation fadeOut=new AlphaAnimation(1,0);
final AnimationSet set = new AnimationSet(false);
set.addAnimation(fadeIn);
set.addAnimation(fadeOut);
fadeOut.setStartOffset(2000);
set.setDuration(2000);
imageView.startAnimation(set);
set.setAnimationListener(new Animation.AnimationListener()
@Override
public void onAnimationStart(Animation animation)
@Override
public void onAnimationRepeat(Animation animation)
@Override
public void onAnimationEnd(Animation animation)
imageView.startAnimation(set);
);
【讨论】:
【参考方案8】:我正在使用这种例程以编程方式链接动画。
final Animation anim_out = AnimationUtils.loadAnimation(context, android.R.anim.fade_out);
final Animation anim_in = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
anim_out.setAnimationListener(new AnimationListener()
@Override
public void onAnimationStart(Animation animation)
@Override
public void onAnimationRepeat(Animation animation)
@Override
public void onAnimationEnd(Animation animation)
////////////////////////////////////////
// HERE YOU CHANGE YOUR IMAGE CONTENT //
////////////////////////////////////////
//ui_image.setImage...
anim_in.setAnimationListener(new AnimationListener()
@Override
public void onAnimationStart(Animation animation)
@Override
public void onAnimationRepeat(Animation animation)
@Override
public void onAnimationEnd(Animation animation)
);
ui_image.startAnimation(anim_in);
);
ui_image.startAnimation(anim_out);
【讨论】:
【参考方案9】:对我来说最好和最简单的方法就是这样..
->只需使用包含 sleep() 的 Handler 创建一个线程。
private ImageView myImageView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shape_count); myImageView= (ImageView)findViewById(R.id.shape1);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.fadein);
myImageView.startAnimation(myFadeInAnimation);
new Thread(new Runnable()
private Handler handler = new Handler()
@Override
public void handleMessage(Message msg)
Log.w("hendler", "recived");
Animation myFadeOutAnimation = AnimationUtils.loadAnimation(getBaseContext(), R.anim.fadeout);
myImageView.startAnimation(myFadeOutAnimation);
myImageView.setVisibility(View.INVISIBLE);
;
@Override
public void run()
try
Thread.sleep(2000); // your fadein duration
catch (Exception e)
handler.sendEmptyMessage(1);
).start();
【讨论】:
【参考方案10】:这可能是您将获得的最佳解决方案。简单易行。我是在udemy上学的。
假设您有两个图像,图像 ID 分别为 id1 和 id2,并且当前图像视图设置为 id1,并且您希望每次有人点击时将其更改为另一个图像。所以这是MainActivity.java
文件中的基本代码
int clickNum=0;
public void click(View view)
clickNum++;
ImageView a=(ImageView)findViewById(R.id.id1);
ImageView b=(ImageView)findViewById(R.id.id2);
if(clickNum%2==1)
a.animate().alpha(0f).setDuration(2000); //alpha controls the transpiracy
else if(clickNum%2==0)
b.animate().alpha(0f).setDuration(2000); //alpha controls the transpiracy
我希望这肯定会有所帮助
【讨论】:
以上是关于Android 使用 ImageView 淡入淡出的主要内容,如果未能解决你的问题,请参考以下文章