ImageView로 Android 페이드 인 및 페이드 아웃


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); 명령을 실행하면 이미지가 즉시 표시되지 않고 페이드 인 애니메이션이 실행될 때만?

답변:


66

이것을 시작했던 방식으로 구현하려면 애니메이션 의 시작과 끝을 감지 할 수 있도록 AnimationListener 를 추가해야합니다 . 페이드 아웃에 대한 onAnimationEnd ()가 호출되면 ImageView 객체의 가시성을 View.INVISIBLE로 설정하고 이미지를 전환하고 애니메이션 페이드 인을 시작할 수 있습니다. 여기에도 또 다른 AnimationListener가 필요합니다. 페이드 인 애니메이션에 대한 onAnimationEnd ()를 받으면 ImageView를 View.VISIBLE로 설정하면 원하는 효과를 얻을 수 있습니다.

이전에 비슷한 효과를 구현했지만 단일 ImageView가 아닌 ​​2 개의 ImageView가 있는 ViewSwitcher 를 사용했습니다 . 페이드 인 및 페이드 아웃을 사용하여 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

@Aldryd 이것이 성능면에서 더 효율적입니까? 선택한 답변 (별도의 XML 파일)과 비교할 때?
Ron

@Ron 나는 다른 방법의 성능을 실제로 비교하지 않았습니다. ImageView 개체에 대한 비트 맵을 디코딩 / 작업하는 것과 비교할 때 ViewSwitcher를 사용하는 것과 AnimationListener를 직접 구현하는 것은 그다지 눈에 띄지 않을 것이라고 생각합니다. 최근에 API 11 이상을 사용하는 경우 새로운 애니메이션 클래스를 사용할 수 있다는 것을 알게되었습니다. API 11을 사용하여 2 개의 뷰를 교차 페이드하는 예는 다음에서 볼 수 있습니다. 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
및 애니메이션 밖으로 페이드가 코드에서 정의 할 수있는 방법을 보여주는를 들어, 선생님, 내 투표 수
헤르 Grumps

onAnimationRepeat 메소드에서 반복 횟수를 계산하고 Array.lenght % count를 수행 할 수도 있습니다
butelo

2
@Crocodile 코드에 메모리 문제가있을 수 있다고 생각하십니까? 위 코드가있는 활동을 계속 실행하십시오. 너무 많은 AnimationSet 객체를 생성합니다. 잠시 후 outOfMemory와 충돌 할 가능성이 있습니까?
Gem

1
당신은 생명의 은인입니다!
faizanjehangir

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

부딪혀서 미안하지만 핸들러에서 이것을 사용하고 영구 루프에두면 앱이 다른 일정한 페이드 인 / 페이드 아웃 애니메이션에서 성능을 잃습니다. 추천 사항이 있습니까?
James

TransitionDrawable은 두 개의 이미지 / 레이어 만 처리 할 수 ​​있습니다.
Signcodeindie

에스프레소 테스트를 실행하면 상태 묘화는 AppNotIdleException의 원인
PK 굽타

6

페이드 인 애니메이션을 사용하여 이전 이미지를 새 이미지로 대체했습니다.

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

2
더 깨끗한 코드는 android-developers.blogspot.com/2011/05/… 를 참조하세요 .
zyamys

감사합니다!! 여전히 관련성이 있습니다 ... 지금 가장 필요한 것!
Teekam Suthar

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. 프로젝트의 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" />

당신 자바 클래스에서

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.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
}

}

나는 이것이 확실히 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.