Android ImageView ile belirir ve kaybolur


89

Yaptığım bir slayt gösterisinde bazı sorunlar yaşıyorum.

Kararmak ve kaybolmak için xml'de 2 animasyon oluşturdum:

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>

Yapmaya çalıştığım şey, solma efektini kullanarak bir ImageView'daki görüntüleri değiştirmektir, böylece o anda görüntülenen görüntü solacak ve bir diğeri belirecektir. Önceden ayarlanmış bir görüntüm olduğunu düşünürsek, bu Görüntüyü olmadan da karartabilirim. sorun, bununla:

    Animation fadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.your_fade_in_anim);
    imageView.startAnimation(fadeoutAnim);

Ama sonra görüntülenecek sonraki görüntüyü ayarlıyorum:

    imageView.setImageBitmap(secondImage);

Sadece imageView'de belirir ve animasyonu ayarladığımda görüntüyü gizler, karartır ... Bunu düzeltmenin bir yolu var mı, yani, imageView.setImageBitmap (secondImage) yaptığımda; komutu, görüntü hemen görünmüyor ve yalnızca animasyonda solma yürütüldüğünde?

Yanıtlar:


66

Bunu başladığınız şekilde uygulamak için , bir animasyonun başlangıcını ve sonunu algılayabilmeniz için bir AnimationListener eklemeniz gerekir . Fade out için onAnimationEnd () çağrıldığında, ImageView nesnenizin görünürlüğünü View.INVISIBLE olarak ayarlayabilir, görüntüleri değiştirebilir ve animasyonda solmaya başlayabilirsiniz - burada başka bir AnimationListener'a da ihtiyacınız olacak. Animasyonda solmanız için onAnimationEnd () aldığınızda, ImageView'u View.VISIBLE olarak ayarlayın ve bu size aradığınız efekti vermelidir.

Daha önce benzer bir efekt uyguladım, ancak tek bir ImageView yerine 2 ImageView ile bir ViewSwitcher kullandım . ViewSwitcher için "içeri" ve "dışarı" animasyonlarını yavaşça açıp kapayarak ayarlayabilirsiniz, böylece AnimationListener uygulamasını yönetebilir. O zaman yapmanız gereken tek şey, 2 ImageView arasında geçiş yapmaktır.

Düzenleme: Biraz daha yararlı olması için, burada ViewSwitcher'ın nasıl kullanılacağına dair hızlı bir örnek verilmiştir. Tam kaynağı https://github.com/aldryd/imageswitcher adresinde ekledim .

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

Teşekkürler dostum! SerVisible'ı unuttum! ViewSwitcher ipucu için teşekkürler, her şeyi tek başıma halletmekten daha kolay görünüyor.
IPValverde

@Aldryd Bu, performans açısından daha verimli mi? Seçilen yanıta kıyasla (ayrı XML dosyası)?
Ron

@Ron Farklı yöntemlerin performansını gerçekten karşılaştırmadım. ImageView nesneleri için bitmap'lerle kod çözme / çalışma ile karşılaştırıldığında, bir ViewSwitcher kullanmak yerine AnimationListener'ı kendinizin uygulamasının çok fark edilmeyeceğini düşünürdüm. Kısa süre önce, API 11 veya üstünü kullanıyorsanız, bazı yeni Animasyon sınıflarını kullanabileceğinizi öğrendim. API 11 ile 2 görünümün çapraz
geçişine

96

Ben de sizinle aynı hedefe ulaşmak istedim, bu yüzden aşağıdaki yöntemi yazdım, eğer ona bir ImageView ve resim çizilebilir referansların bir listesini iletirseniz tam olarak bunu yapar.

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


Ayrıca tekrarları sayabilir ve onAnimationRepeat yönteminde bir Array.lenght% count yapabilirsiniz
butelo

2
@Crocodile Kodunuzda bellek sorunu olabileceğini düşünüyor musunuz? Yukarıdaki koda sahip aktivitenin devam etmesine izin verin. Çok fazla AnimationSet Nesnesi yaratacak. Bir süre sonra outOfMemory ile çökme olasılığı var mı?
Gem

1
Siz bayım bir cankurtaransınız!
faizanjehangir

2
@Gem - bu özel tahsis neden bir soruna neden olsun? İmageView.setAnimation (animasyon) olarak adlandırıldığında, önceki bir animasyona yapılan herhangi bir referans kaybolduğunda, çöp toplayıcı bu önceki nesneyi silebilir. AFAIK, hafıza sorunu değil.
greg7gkb

46

Özel animasyonlar yerine TransitionDrawable kullanmayı düşündünüz mü? https://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html

Aradığınız şeyi başarmanın bir yolu şudur:

// 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
Bu soru için en iyi cevap budur.
DragonT

Çarpma için özür dilerim, ancak bunu bir İşleyicide kullanırsam ve bunu kalıcı bir döngüde kullanırsam, uygulama sahip olduğum başka bir sabit solma / kaybolma animasyonunda performansını kaybeder. Herhangi bir tavsiye var mı?
James

TransitionDrawable yalnızca iki görüntüyü / katmanı işleyebilir.
Signcodeindie

Geçiş çekilebilirliği, espresso testini çalıştırırken AppNotIdleException'a neden oluyor
PK Gupta


3

Aladin Q'nun çözümüne dayanarak, burada yazdığım, animasyonda biraz solma / kaybolma sırasında görüntüyü değiştirecek bir yardımcı işlev:

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

bunu iki basit noktayla yapabilir ve kodunuzu değiştirebilirsiniz

1. xml in projenizin anim klasöründe, Fade in ve fade out süresini ayarlayın

2. java sınıfınızda, karartma animasyonunun başlamasından önce, ikinci imageView görünürlüğünü ayarlayın Gitti ve sonra animasyon başlatıldıktan sonra, görünürde solmasını istediğiniz ikinci imageView görünürlüğünü ayarlayın

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 sınıfında

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

Sonsuz Fade In and Out için

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

Programlı olarak zincirleme animasyonlar için bu tür bir rutin kullanıyorum.

    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

Benim için en iyi ve en kolay yol şuydu ..

-> İşleyicide uyku () içeren bir iş parçacığı oluşturun.

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

Bu muhtemelen alacağınız en iyi çözümdür. Basit ve kolay. Udemy'de öğrendim. Sırasıyla resim kimliği id1 ve id2'ye sahip iki resminiz olduğunu ve şu anda resim görünümü id1 olarak ayarlandığını ve birisi her tıkladığında bunu diğer resimle değiştirmek istediğinizi varsayalım. Bu, MainActivity.javaDosya'daki temel koddur.

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
}

}

Umarım bu kesinlikle yardımcı olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.