Android появляется и исчезает с помощью ImageView


89

У меня проблемы со слайд-шоу, которое я создаю.

Я создал 2 анимации в xml для постепенного появления и исчезновения:

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); , изображение не отображается сразу, и только когда выполняется плавное появление анимации?

Ответы:


66

Чтобы реализовать это так, как вы начали, вам нужно добавить AnimationListener, чтобы вы могли определять начало и конец анимации. Когда вызывается onAnimationEnd () для постепенного исчезновения, вы можете установить видимость вашего объекта ImageView на View.INVISIBLE, переключить изображения и начать плавную анимацию - вам также понадобится еще один AnimationListener. Когда вы получаете onAnimationEnd () для затухающей анимации, установите для ImageView значение View.VISIBLE, и это должно дать вам эффект, который вы ищете.

Я реализовал подобный эффект раньше, но я использовал ViewSwitcher с двумя ImageView, а не с одним ImageView. Вы можете установить «вход» и «выход» анимации для ViewSwitcher с вашим постепенным появлением и исчезновением, чтобы он мог управлять реализацией AnimationListener. Затем все, что вам нужно сделать, - это переключаться между двумя 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 04

@Aldryd Это более эффективно с точки зрения производительности? По сравнению с выбранным ответом (отдельный XML-файл)?
Рон

@Ron Я не особо сравнивал производительность разных методов. По сравнению с декодированием / работой с растровыми изображениями для объектов ImageView, я бы подумал, что использование ViewSwitcher по сравнению с собственной реализацией AnimationListener было бы не очень заметно. Недавно я узнал, что если вы используете API 11 или выше, вы можете использовать некоторые новые классы анимации. Вы можете увидеть пример перекрестного затухания 2 представлений с API 11 здесь: developer.android.com/training/animation/crossfade.html
Aldryd

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

Вы также можете подсчитывать повторы и делать подсчет Array.lenght% в своем методе
onAnimationRepeat

2
@Crocodile Как вы думаете, в вашем коде может быть проблема с памятью? Пусть действие с приведенным выше кодом продолжается. Это создаст так много объектов AnimationSet. Есть ли вероятность, что через некоторое время он выйдет из строя с outOfMemory?
Gem

1
Вы, сэр, палочка-выручалочка!
Файзанджехангир

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

Извините за неровности, но если я использую это в обработчике и использую его в постоянном цикле, приложение теряет производительность в другой имеющейся у меня постоянной анимации постепенного появления / исчезновения. Какие-нибудь рекомендации?
Джеймс

TransitionDrawable может обрабатывать только два изображения / слой.
Signcodeindie 01

Переход с возможностью рисования вызывает исключение AppNotIdleException при запуске теста эспрессо
П.К. Гупта

6

Я использовал анимацию fadeIn, чтобы заменить новое изображение на старое.

ObjectAnimator.ofFloat(imageView, View.ALPHA, 0.2f, 1.0f).setDuration(1000).start();

2
См. Android-developers.blogspot.com/2011/05/… для более чистого кода.
zyamys 02 фев.15,

СПАСИБО!! все еще актуально ... Что мне было нужно больше всего прямо сейчас!
Тикам Сутар

1
Спасибо!! Это лучший ответ ... очень просто реализовать и работает без сбоев.
user3152377

3

На основе решения Aladin Q, вот вспомогательная функция, которую я написал, которая изменит изображение в просмотре изображения при небольшом затухании / затухании анимации:

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.В вашем xml в папке anim вашего проекта установите время затухания и затухания, не равное

2.В вашем классе java перед началом исчезновения анимации установите вторую видимость imageView Gone, затем после начала исчезновения анимации установите вторую видимость 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 ().

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

Вероятно, это лучшее решение, которое вы получите. Просто и легко. Узнал на удемы. Предположим, у вас есть два изображения с идентификаторами изображения 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
}

}

Надеюсь, это обязательно поможет

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.