Android使用ImageView淡入和淡出


89

我正在制作幻灯片时遇到一些麻烦。

我在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);。命令,仅在执行淡入淡出动画时,图像不会立即显示?

Answers:


65

要以开始的方式实现此功能,您需要添加一个AnimationListener以便可以检测的开始和结束。调用用于淡出的onAnimationEnd()时,可以将ImageView对象的可见性设置为View.INVISIBLE,切换图像并开始进行淡入动画-这里也需要另一个AnimationListener。当收到onAnimationEnd()用于淡入淡出的动画时,将ImageView设置为View.VISIBLE,这应该可以为您提供所需的效果。

之前我已经实现了类似的效果,但是我将ViewSwitcher与2个ImageViews而不是单个ImageView一起使用。您可以在淡入和淡出时为ViewSwitcher设置“入”和“出”动画,以便它可以管理AnimationListener实现。然后,您要做的就是在2个ImageView之间切换。

编辑: 要有用一点,这是一个如何使用ViewSwitcher的快速示例。我已经在https://github.com/aldryd/imageswitcher上包含了完整的源代码。

activity_main.xml

    <ViewSwitcher
        android:id="@+id/switcher"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:inAnimation="@anim/fade_in"
        android:outAnimation="@anim/fade_out" >

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitCenter"
            android:src="@drawable/sunset" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            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技巧,这似乎比我自己处理所有事情容易。
IPValverde 2012年

@Aldryd这是更有效的表现方式吗?与所选答案(单独的XML文件)相比?
罗恩

@Ron我并没有真正比较不同方法的性能。与对ImageView对象的位图进行解码/处理相比,我认为使用ViewSwitcher而不是自己实现AnimationListener不会很明显。我最近确实发现,如果您使用的是API 11或更高版本,则可以使用一些新的Animation类。您可以在此处查看使用API​​ 11进行渐变2视图的示例:developer.android.com/training/animation/crossfade.html
Aldryd 2013年

96

我想实现与您相同的目标,因此我编写了以下方法,如果您将其传递给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
        }
    });
}

1
为了展示如何在代码中定义淡入和淡出动画,请先生,请投票给我
Herr Grumps 2012年

您还可以计算重复次数,并在onAnimationRepeat方法中执行Array.lenght%count
butelo 2013年

2
@Crocodile您认为代码中可能存在内存问题。让带有以上代码的活动继续运行。它将创建许多AnimationSet对象。一段时间后,它是否会因outOfMemory而崩溃?
2013年

1
先生,您是救命稻草!
faizanjehangir 2014年

2
@Gem-为什么该特定分配会引起问题?每次调用imageView.setAnimation(animation)时,对先前动画的任何引用都将丢失,因此垃圾收集器将能够删除此先前对象。AFAIK,不是内存问题。
greg7gkb

46

您是否考虑过使用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);

2
这是此问题的最佳答案。
DragonT

很抱歉碰碰,但是如果我在Handler中使用它,并使其永久循环,则该应用会在我拥有的其他恒定淡入/淡出动画中失去性能。有什么建议吗?
詹姆斯,

TransitionDrawable每层只能处理两个图像。
Signcodeindie'3

进行特浓咖啡测试时,可转换的过渡绘制导致AppNotIdleException
PK Gupta,


3

基于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);
    }

3

您可以通过两个简单的步骤完成操作,然后更改代码

1.在项目的anim文件夹中的xml中,设置淡入和淡出持续时间不相等

2.在淡出动画开始之前的java类中,设置第二个imageView可见性消失,然后在淡出动画开始后设置要淡入可见的第二个imageView可见性

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

3

无限淡入和淡出

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

1

我正在使用这种例程以编程方式链接动画。

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

1

对我而言,最好和最简单的方法就是这样。

->只需使用包含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();
}

1

这可能是您将获得的最佳解决方案。简单又容易。我是从udemy中学到的。假设您有两个图像,分别具有图像ID为ID1和ID2,并且当前图像视图设置为ID1,并且您希望每次有人单击时将其更改为另一个图像。因此,这是MainActivity.javaFile中的基本代码

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
}

}

我希望这一定会有所帮助

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.