Animowany obraz ładowania w Picassie


105

Mam następujący kod, aby załadować obraz w Picassie, używając elementu rysunkowego dla symbolu zastępczego do wyświetlenia podczas pobierania obrazu. Chcę jednak animowanego obracającego się pokrętła w stylu paska postępu, który animuje dookoła i dookoła podczas ładowania obrazu, tak jak w większości profesjonalnych aplikacji. Picasso nie wydaje się wspierać tego, tylko statyczne obrazy do rysowania. Czy istnieje sposób, aby to zadziałało z Picassem, czy też muszę zrobić coś innego?

Picasso.with(context).load(url)             
                    .placeholder(R.drawable.loading)
                    .error(R.drawable.image_download_error)
                    .into(view);

Odpowiedzi:


252

Jak uzyskać obraz animacji postępu ładowania za pomocą symbolu zastępczego Picassa:

Rozwiązałem to łatwo, używając animowanego obracanego obiektu XML.

Kroki:

progress_image.png

progress_image.png

/res/drawable/progress_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item android:gravity="center">
    <animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/progress_image"
        android:pivotX="50%"
        android:pivotY="50%" />
    </item>
</layer-list>

Ładowanie Picassa:

Picasso.with( context )
        .load( your_path )
        .error( R.drawable.ic_error )
        .placeholder( R.drawable.progress_animation )
        .into( image_view );

32
@DBragion działa świetnie, ale w przypadku dużych obrazów spadł. czy możemy ustalić jego szerokość i wysokość na liczbę taką jak 32x32 piksele?
m3hdi

9
To nie działa, brak animacji. Tylko zwykły obraz
Joe Maher,

4
Działa, ale chcę, aby mały program ładujący nie był moim programem ładującym rozmiar obrazu
Ganpat Kaliya

2
Działając dobrze, animacja pozostaje mała do kilku milisekund przed pojawieniem się pobranego obrazu, zostaje zmaksymalizowana i rozciągnięta na kilka milisekund, a następnie pojawia się obraz. Czy jest jakieś rozwiązanie?
tinyCoder

2
Użyj romannurik.github.io/AndroidAssetStudio/index.html (wybierz „Generator ikon programu uruchamiającego”), aby utworzyć mdpi, hdpi, xhdpi itd.
CoolMind

73

Zaimplementowałem okno dialogowe postępu do momentu pobrania obrazu i jest bardzo proste. Weź swój ImageView we względnym układzie i umieść program ładujący postęp w tym samym widoku obrazu. Zastosuj poniższy kod i obsłuż tylko widoczność okna dialogowego postępu.

holder.loader.setVisibility(View.VISIBLE);
            holder.imageView.setVisibility(View.VISIBLE);
         final ProgressBar progressView = holder.loader;
            Picasso.with(context)
            .load(image_url)
            .transform(new RoundedTransformation(15, 0))
            .fit()
            .into(holder.imageView, new Callback() {
                @Override
                public void onSuccess() {
                    progressView.setVisibility(View.GONE);
                }

                @Override
                public void onError() {
                    // TODO Auto-generated method stub

                }
            });
        }

Cieszyć się. :)


Dzięki… to mi bardzo pomogło :)
Zohair

2
Wspaniały! Jak dotąd najlepsze rozwiązanie, może być stosowane w wielu różnych kontekstach. :)
VVZen

7
Właściwie powinieneś zwrócić uwagę na słabe referencje i zadeklarować obiekt Callback w ten sposób , aby uniknąć zbierania śmieci (w przeciwnym razie onSuccess nigdy nie zostałby wywołany):final Callback loadedCallback = new Callback() { @Override public void onSuccess() { // your code } @Override public void onError() { // your code } }; imageView.setTag(loadedCallback); Picasso.with(context).load(url).into(imageView, loadedCallback);
VVZen

Każdy zdezorientowany żargonem Progress Loader to Progress Bad
Joe Maher

2
Brakowało Ci dodania klasy RoundedTransformation. Ta klasa jest tutaj gist.github.com/aprock/6213395
Md. Sajedul Karim

3

Picasso nie obsługuje niestety animowanych symboli zastępczych.

Jednym ze sposobów obejścia tego jest umieszczenie ImageView w FrameLayout z animowanym rysunkiem pod spodem. W ten sposób, gdy Picasso wczytuje obraz, załaduje się on nad animowanym elementem zastępczym, dając użytkownikowi zamierzony efekt.

Alternatywnie możesz załadować obraz do elementu docelowego . Wtedy pasek postępu byłby wyświetlany domyślnie, a gdy wywoływana jest metoda onBitmapLoaded, można ją ukryć i wyświetlić obraz. Widać podstawową realizację tego tutaj


3
Picasso nie obsługują animowanych zastępcze. Piszesz plik animacji do rysowania (zawiera listę animacji z kilkoma elementami reprezentującymi każdy obraz w animacji). Podajesz ten plik do nowego obiektu AnimationDrawable, a następnie przekazujesz go do metody placeHolder () w konstruktorze programu ładującego Picasso.
Odaym

1

Po prostu dodaj atrybut kształtu w odpowiedzi DBragion, jak poniżej, a będzie działać jak urok. Miłego kodowania.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>

        <shape
            android:shape="rectangle">

            <size
                android:width="200dp"
                android:height="200dp"/>

            <solid
                android:color="#00FFFFFF"/>
        </shape>
    </item>

    <item android:gravity="center">
        <animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
            android:drawable="@drawable/spinner"
            android:pivotX="50%"
            android:pivotY="50%" />
    </item>
</layer-list>

Możesz także użyć Glide:

Glide.with(activity).load(url)
                    .apply(RequestOptions.centerInsideTransform())
                    .placeholder(R.drawable.progress_animation)
                    .into(imageview);

1

Znalazłem odpowiedź na to pytanie!

Zobacz: https://github.com/square/picasso/issues/427#issuecomment-266276253

Oprócz odpowiedzi @DBragion spróbuj poniżej.

Teraz możemy ustalić wysokość i szerokość!

image_view.scaleType = ImageView.ScaleType.CENTER_INSIDE
picasso.load(your_path)
        .fit()
        .centerCrop()
        .noFade()
        .placeholder(R.drawable. progress_animation)
        .into(image_view)

Myślę, że są dwie kluczowe kwestie.

  1. użyj noFade ()

  2. ustaw scaleType image_view na „CENTER_INSIDE”


0

Zrobiłem to działało w następujący sposób:

  1. Stworzyłem drawable (znalezione gdzieś w Internecie) i umieściłem go w res / drawable:

    <?xml version="1.0" encoding="utf-8"?>
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="90"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360">
    
    <shape
        android:innerRadiusRatio="3"
        android:shape="ring"
        android:thicknessRatio="7.0">
    
        <gradient
            android:angle="0"
            android:centerColor="#007DD6"
            android:endColor="#007DD6"
            android:startColor="#007DD6"
            android:type="sweep"
            android:useLevel="false" />
    </shape>

  2. W moim elemencie dla GridView dodano element ProgressBar:

    <ProgressBar
        android:id="@+id/movie_item_spinner"
        android:layout_width="@dimen/poster_width"
        android:layout_height="@dimen/poster_height"
        android:progressDrawable="@drawable/circular_progress_bar"/>
  3. W Adapterze dodano Target Object z następującymi parametrami, gdzie poster i spinner są odniesieniami do ImageView i ProgressBar:

    // Cel, aby pokazać / ukryć ProgressBar w ImageView

    final Target target = new Target() {
    
            @Override
            public void onPrepareLoad(Drawable drawable) {
                poster.setBackgroundResource(R.color.white);
                spinner.setVisibility(View.VISIBLE);
            }
    
            @Override
            public void onBitmapLoaded(Bitmap photo, Picasso.LoadedFrom from) {
                poster.setBackgroundDrawable(new BitmapDrawable(photo));
                spinner.setVisibility(View.GONE);
            }
    
            @Override
            public void onBitmapFailed(Drawable drawable) {
                poster.setBackgroundResource(R.color.white);
            }
        };
  4. Wyniki będą takie podczas ładowania - kółko się obraca (przepraszam za ten zrzut ekranu, ale obrazy pojawiają się zbyt szybko): ScreenShot


0

Dla każdego, kto próbuje użyć techniki DBragion: Upewnij się, że masz najnowszą wersję Picassa, inaczej nie będzie się kręcić. Mój nie działał, dopóki nie użyłem wersji 2.5.2.

compile 'com.squareup.picasso:picasso:2.5.2'

6
To powinien być komentarz pod wspomnianą odpowiedzią
Ojonugwa Jude Ochalifu

0

W tym linku Jake Wharton powiedział:

Nie. Używamy Android BitmapFactory do dekodowania wszystkich obrazów i nie ma on obsługi animowanych plików GIF (niestety).

Wtedy nie możesz


0

Po prostu użyj Picasso PlaceHolder

  Picasso.get()
        .load(datas[position].artist?.image)
        .placeholder(R.drawable.music_image)
        .error(R.drawable.music_image)
        .into(holder.cardViewImage)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.