Android wird mit ImageView ein- und ausgeblendet


89

Ich habe einige Probleme mit einer Diashow, die ich erstelle.

Ich habe 2 Animationen in XML zum Ein- und Ausblenden erstellt:

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>

Wenn Sie versuchen, Bilder aus einer ImageView mithilfe des Überblendungseffekts zu ändern, wird das aktuell angezeigte Bild ausgeblendet und ein anderes eingeblendet. Da ich bereits ein Bild festgelegt habe, kann ich dieses Bild ohne ausblenden Problem damit:

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

Aber dann stelle ich das nächste Bild ein, das angezeigt werden soll:

    imageView.setImageBitmap(secondImage);

Es wird nur in der imageView angezeigt, und wenn ich die Animation einstelle, wird das Bild ausgeblendet, eingeblendet ... Gibt es eine Möglichkeit, dies zu beheben, wenn ich imageView.setImageBitmap (secondImage) mache? Befehl, wird das Bild nicht sofort angezeigt und nur, wenn die Einblendanimation ausgeführt wird?

Antworten:


65

Um dies so zu implementieren, wie Sie es begonnen haben, müssen Sie einen AnimationListener hinzufügen, damit Sie den Anfang und das Ende einer Animation erkennen können. Wenn onAnimationEnd () für das Ausblenden aufgerufen wird, können Sie die Sichtbarkeit Ihres ImageView-Objekts auf View.INVISIBLE setzen, die Bilder wechseln und mit dem Einblenden der Animation beginnen - auch hier benötigen Sie einen weiteren AnimationListener. Wenn Sie onAnimationEnd () für Ihre eingeblendete Animation erhalten, setzen Sie die ImageView auf View.VISIBLE. Dies sollte Ihnen den gewünschten Effekt verleihen.

Ich habe zuvor einen ähnlichen Effekt implementiert, aber ich habe einen ViewSwitcher mit 2 ImageViews anstelle einer einzelnen ImageView verwendet. Sie können die "In" - und "Out" -Animationen für den ViewSwitcher mit Ein- und Ausblenden festlegen, um die AnimationListener-Implementierung zu verwalten. Dann müssen Sie nur noch zwischen den beiden ImageViews wechseln.

Bearbeiten: Um ein bisschen nützlicher zu sein, finden Sie hier ein kurzes Beispiel für die Verwendung des ViewSwitcher. Ich habe die vollständige Quelle unter https://github.com/aldryd/imageswitcher aufgenommen .

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

Danke, Mann! Ich habe das serVisible vergessen! Und danke für den ViewSwitcher-Tipp, es scheint einfacher zu sein, als alles alleine zu erledigen.
IPValverde

@Aldryd Ist das in Bezug auf die Leistung effizienter? Im Vergleich zur ausgewählten Antwort (separate XML-Datei)?
Ron

@ Ron Ich habe die Leistung der verschiedenen Methoden nicht wirklich verglichen. Im Vergleich zum Dekodieren / Arbeiten mit Bitmaps für die ImageView-Objekte würde ich denken, dass die Verwendung eines ViewSwitcher im Vergleich zur Implementierung des AnimationListener selbst nicht sehr auffällig wäre. Ich habe kürzlich herausgefunden, dass Sie bei Verwendung von API 11 oder höher einige neue Animationsklassen verwenden können. Sie können ein Beispiel für das Überblenden von 2 Ansichten mit API 11 hier sehen: developer.android.com/training/animation/crossfade.html
Aldryd

96

Ich wollte das gleiche Ziel wie Sie erreichen, deshalb habe ich die folgende Methode geschrieben, die genau das tut, wenn Sie eine ImageView und eine Liste mit Verweisen auf Bildzeichnungen übergeben.

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
Um zu zeigen, wie die Ein- und Ausblendanimationen im Code definiert werden können, erhalten Sie meine Stimme
Herr Grumps,

Sie können auch Wiederholungen zählen und eine Array.lenght% -Zählung in Ihrer onAnimationRepeat-Methode durchführen
butelo

2
@Crocodile Glaubst du, dass dein Code ein Speicherproblem haben könnte? Lassen Sie die Aktivität mit dem obigen Code weiterlaufen. Es werden so viele AnimationSet-Objekte erstellt. Gibt es eine Möglichkeit, dass es nach einiger Zeit mit outOfMemory abstürzt?
Gem

1
Sie, mein Herr, sind ein Lebensretter!
Faizanjehangir

2
@Gem - warum würde diese bestimmte Zuordnung ein Problem verursachen? Jedes Mal, wenn imageView.setAnimation (Animation) aufgerufen wird, geht ein Verweis auf eine vorherige Animation verloren, sodass der Garbage Collector dieses vorherige Objekt löschen kann. AFAIK, kein Speicherproblem.
Greg7gkb

46

Haben Sie daran gedacht, TransitionDrawable anstelle von benutzerdefinierten Animationen zu verwenden? https://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html

Ein Weg, um das zu erreichen, wonach Sie suchen, ist:

// 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
Dies ist die beste Antwort auf diese Frage.
DragonT

Entschuldigen Sie das Anstoßen, aber wenn ich dies in einem Handler verwende und es in einer permanenten Schleife habe, verliert die App die Leistung in einer anderen konstanten Ein- / Ausblendanimation, die ich habe. Irgendwelche Empfehlungen?
James

TransitionDrawable kann nur zwei Bilder / Ebenen verarbeiten.
Signcodeindie

Übergang zeichnbar verursacht AppNotIdleException beim Ausführen des Espressotests
PK Gupta


3

Basierend auf der Lösung von Aladin Q ist hier eine Hilfsfunktion, die ich geschrieben habe und die das Bild in einer Bildansicht ändert, während ein wenig Ausblenden / Einblenden der Animation ausgeführt wird:

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

Sie können dies durch zwei einfache Punkte tun und Ihren Code ändern

1.Stellen Sie in Ihrem XML-Ordner im Animationsordner Ihres Projekts die Ein- und Ausblenddauer ungleich ein

2.Stellen Sie in Ihrer Java-Klasse vor dem Start der Ausblendanimation die zweite Sichtbarkeit der Bildansicht ein. Nachdem die Ausblendanimation gestartet wurde, stellen Sie die zweite Sichtbarkeit der Bildansicht ein, die Sie sichtbar einblenden möchten

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" />

In deiner Java-Klasse

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

2

Für unendliches Ein- und Ausblenden

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

Ich verwende diese Art von Routine zum programmgesteuerten Verketten von Animationen.

    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

Der beste und einfachste Weg war für mich dieser ..

-> Erstellen Sie einfach einen Thread mit Handler, der sleep () enthält.

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

Dies ist wahrscheinlich die beste Lösung, die Sie bekommen werden. Simpel und einfach. Ich habe es auf udemy gelernt. Angenommen, Sie haben zwei Bilder mit den Bild-IDs id1 und id2, und derzeit ist die Bildansicht auf id1 festgelegt, und Sie möchten sie jedes Mal, wenn jemand darauf klickt, in das andere Bild ändern. Dies ist also der Basiscode in MainActivity.javaDatei

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
}

}

Ich hoffe das wird sicherlich helfen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.