Android mờ dần và mờ dần với ImageView


89

Tôi đang gặp một số rắc rối với trình chiếu mà tôi đang tạo.

Tôi đã tạo 2 hoạt ảnh trong xml để mờ dần và mờ dần:

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>

Điều tôi không thể làm là thay đổi hình ảnh từ ImageView bằng hiệu ứng mờ dần, vì vậy hình ảnh hiện đang hiển thị sẽ mờ dần và một hình khác sẽ mờ dần. Xem xét rằng tôi đã đặt sẵn một hình ảnh, tôi có thể làm mờ Hình ảnh này mà không cần vấn đề, với điều này:

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

Nhưng sau đó, tôi đặt hình ảnh tiếp theo được hiển thị:

    imageView.setImageBitmap(secondImage);

Nó chỉ hiển thị trong imageView, và khi tôi đặt hoạt ảnh, nó sẽ ẩn hình ảnh, làm mờ hình ảnh ... Có cách nào để khắc phục điều đó không, ý tôi là khi tôi thực hiện imageView.setImageBitmap (secondImage); lệnh, hình ảnh không hiển thị ngay lập tức, và chỉ khi làm mờ dần trong hoạt ảnh được thực hiện?

Câu trả lời:


66

Để thực hiện điều này theo cách bạn đã bắt đầu, bạn sẽ cần thêm AnimationListener để bạn có thể phát hiện phần đầu và phần cuối của hoạt ảnh. Khi onAnimationEnd () for fade out được gọi, bạn có thể đặt khả năng hiển thị của đối tượng ImageView thành View.INVISIBLE, chuyển đổi hình ảnh và bắt đầu làm mờ dần trong hoạt ảnh - bạn cũng sẽ cần một AnimationListener khác ở đây. Khi bạn nhận được onAnimationEnd () cho hiệu ứng mờ dần trong hoạt ảnh, hãy đặt ImageView thành View.VISIBLE và điều đó sẽ mang lại cho bạn hiệu ứng mà bạn đang tìm kiếm.

Tôi đã thực hiện một hiệu ứng tương tự trước đây, nhưng tôi đã sử dụng ViewSwitcher với 2 ImageView thay vì một ImageView. Bạn có thể đặt hoạt ảnh "vào" và "ra" cho ViewSwitcher với độ mờ dần và mờ dần để nó có thể quản lý việc triển khai AnimationListener. Sau đó, tất cả những gì bạn cần làm là xen kẽ giữa 2 ImageView.

Chỉnh sửa: Để hữu ích hơn một chút, đây là ví dụ nhanh về cách sử dụng ViewSwitcher. Tôi đã bao gồm nguồn đầy đủ tại 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();
            }
        }
    });

Cảm ơn anh bạn! Tôi đã quên về serVnable! Và cảm ơn vì mẹo ViewSwitcher, nó có vẻ dễ dàng hơn so với việc tự mình xử lý mọi thứ.
IPValverde

@Aldryd Điều này có hiệu quả hơn không? So với câu trả lời đã chọn (tệp XML riêng biệt)?
Ron

@Ron Tôi không thực sự so sánh hiệu suất của các phương pháp khác nhau. So với việc giải mã / làm việc với bitmap cho các đối tượng ImageView, tôi nghĩ rằng việc sử dụng ViewSwitcher so với việc tự mình triển khai AnimationListener sẽ không đáng chú ý lắm. Gần đây tôi đã phát hiện ra rằng nếu bạn đang sử dụng API 11 trở lên, bạn có thể sử dụng một số lớp Hoạt ảnh mới. Bạn có thể xem ví dụ về crossfading 2 quan điểm với API 11 ở đây: developer.android.com/training/animation/crossfade.html
Aldryd

96

Tôi muốn đạt được mục tiêu giống như bạn, vì vậy tôi đã viết phương pháp sau đây thực hiện chính xác điều đó nếu bạn chuyển nó một ImageView và danh sách các tham chiếu đến các tệp có thể vẽ được hình ảnh.

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
Cho thấy như thế nào phai trong và ngoài hình ảnh động có thể được định nghĩa trong mã, bạn ạ, có được phiếu bầu của tôi
Herr Grumps

Bạn cũng có thể đếm lặp đi lặp lại và làm một Array.lenght% count trong phương pháp onAnimationRepeat của bạn
butelo

2
@Crocodile Bạn có nghĩ rằng có thể có sự cố bộ nhớ trong mã của mình không. Hãy để hoạt động với mã trên tiếp tục chạy. Nó sẽ tạo ra rất nhiều Đối tượng AnimationSet. Có khả năng nó sẽ gặp sự cố với outOfMemory sau một thời gian không?
Gem

1
Ngài là một cái phao cứu sinh!
faizanjehangir

2
@Gem - tại sao việc phân bổ cụ thể đó lại gây ra sự cố? Mỗi khi imageView.setAnimation (hoạt ảnh) được gọi là bất kỳ tham chiếu nào đến hoạt ảnh trước đó đều bị mất, vì vậy trình thu gom rác sẽ có thể xóa đối tượng trước đó này. AFAIK, không phải là vấn đề về bộ nhớ.
greg7gkb

46

Bạn đã nghĩ đến việc sử dụng TransitionDrawable thay vì hoạt ảnh tùy chỉnh chưa? https://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html

Một cách để đạt được những gì bạn đang tìm kiếm là:

// 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
Đây là câu trả lời tốt nhất cho câu hỏi này.
DragonT

Xin lỗi vì sự cố va chạm, nhưng nếu tôi sử dụng điều này trong Trình xử lý và sử dụng nó trong vòng lặp vĩnh viễn, ứng dụng sẽ mất hiệu suất trong một hoạt ảnh mờ dần / mờ dần khác mà tôi có. Bất kỳ đề xuất?
James

TransitionDrawable chỉ có thể xử lý hai hình ảnh / lớp.
Signcodeindie

Chuyển drawable gây AppNotIdleException khi chạy thử nghiệm espresso
PK Gupta

6

Tôi đã sử dụng hoạt ảnh fadeIn đã qua sử dụng để thay thế hình ảnh mới cho hình ảnh cũ

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

2
Xem android-developers.blogspot.com/2011/05/… để biết mã sạch hơn.
zyamys

CẢM ƠN BẠN!! vẫn còn phù hợp ... Điều tôi cần nhất lúc này!
Teekam Suthar

1
Cảm ơn bạn!! Đây là câu trả lời tốt nhất ... rất đơn giản để thực hiện và hoạt động trơn tru.
user3152377

3

Dựa trên giải pháp của Aladin Q, đây là một chức năng trợ giúp mà tôi đã viết, sẽ thay đổi hình ảnh trong chế độ xem hình ảnh trong khi chạy một chút mờ dần / mờ dần trong hoạt ảnh:

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

bạn có thể làm điều đó bằng hai điểm đơn giản và thay đổi mã của bạn

1.Trong thư mục xml in anim của dự án của bạn, Đặt thời gian thời gian làm mờ dần và mờ dần không bằng nhau

2. Trong lớp java của bạn trước khi bắt đầu hoạt ảnh mờ dần, đặt chế độ hiển thị imageView thứ hai Đi rồi sau khi hoạt ảnh mờ dần bắt đầu đặt chế độ hiển thị imageView thứ hai mà bạn muốn làm mờ dần trong hiển thị

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

Trong lớp java của bạn

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

Cho Fade In and Out vô hạn

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

Tôi đang sử dụng loại quy trình này để xâu chuỗi hoạt ảnh theo chương trình.

    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

Cách tốt nhất và dễ nhất, đối với tôi là ..

-> Đơn giản chỉ cần tạo một luồng với Handler chứa 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

Đây có lẽ là giải pháp tốt nhất mà bạn sẽ nhận được. Đơn giản và dễ dàng. Tôi đã học nó trên udemy. Giả sử bạn có hai hình ảnh có id hình ảnh là id1 và id2 tương ứng và hiện tại chế độ xem hình ảnh được đặt là id1 và bạn muốn thay đổi nó thành hình ảnh khác mỗi khi ai đó nhấp vào. Vì vậy, đây là mã cơ bản trong MainActivity.javaTệp

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
}

}

Tôi hy vọng điều này chắc chắn sẽ giúp ích

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.