Анимированная загрузка изображения в Picasso

У меня есть следующий код для загрузки изображения в Picasso, используя рисование для заполнителя для отображения во время загрузки изображения. Что мне нужно, так это анимированный спиннинг-индикатор, который анимируется по кругу во время загрузки изображения, как я вижу в большинстве профессиональных приложений. Пикассо, кажется, не поддерживает это, только статичные изображения. Есть ли способ заставить его работать с Пикассо или мне нужно сделать что-то другое?

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

12 ответов

Как получить анимационное изображение процесса загрузки с использованием заполнителя Picasso:

Я решил это легко с помощью анимированного поворота объекта XML.

шаги:

progress_image.png

progress_image.png

/res/drawable/progress_animation.xml

<?xml version="1.0" encoding="utf-8"?>

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

Загрузка Пикассо:

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

Надеюсь, это поможет!

Я реализовал диалог прогресса, пока изображение не загрузилось, и все очень просто. Возьмите ImageView в относительной компоновке и поместите загрузчик прогресса в то же изображение. Примените приведенный ниже код и обрабатывайте только видимость диалога прогресса.

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

                }
            });
        }

Наслаждаться.:)

К сожалению, Picasso не поддерживает анимированные заполнители.

Один из способов обойти это - поместить ImageView в FrameLayout с анимированным рисунком внизу. Таким образом, когда Picasso загружает изображение, оно загружается поверх анимированного заполнителя, предоставляя пользователю ожидаемый эффект.

Кроме того, вы можете загрузить изображение в цель. Тогда у вас будет индикатор выполнения, отображаемый по умолчанию, а когда вызывается метод onBitmapLoaded, вы можете скрыть его и отобразить изображение. Вы можете увидеть базовую реализацию этого здесь

Я пробовал много способов переполнения стека и, наконец, нашел способ сделать это с помощью « CircularProgressDrawable ». Ссылка: https://developer.android.com/reference/androidx/swiperefreshlayout/widget/CircularProgressDrawable

Пример кода Котлин

      fun Context.loadImage(view: ImageView, url: String) {
  val circularProgressDrawable = CircularProgressDrawable(this)
  circularProgressDrawable.apply {
    strokeWidth = 5f
    centerRadius = 30f
    setColorSchemeColors(
      getColor(Color.WHITE)
    )
    start()
  }

  Picasso
    .get()
    .load(url)
    .fit()
    .centerInside()
    .placeholder(circularProgressDrawable)
    .into(view)
}
         // create a ProgressDrawable object which we will show as placeholder
    CircularProgressDrawable progress = new CircularProgressDrawable(context);
    progress.setColorSchemeColors(R.color.colorPrimary, R.color.colorPrimaryDark, R.color.colorAccent);
    progress.setCenterRadius(30f);
    progress.setStrokeWidth(5f);
    progress.start();

Picasso.with(context).load((String) chatMessage.getPath()).error(R.drawable.error)
                    .placeholder(progress)
                    .noFade()
                    .into(viewHolder.imageBody);

Просто добавьте атрибут shape в ответ DBragion, как показано ниже, и он будет работать как шарм. Удачного кодирования.

<?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>

Вы также можете использовать Glide:

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

Я нашел ответ на этот вопрос!

См. https://github.com/square/picasso/issues/427

В дополнение к ответу @DBragion попробуйте ниже.

Теперь мы можем исправить высоту и ширину!

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

Я думаю, есть два ключевых момента.

  1. используйте noFade()

  2. установите scaleType image_view на "CENTER_INSIDE"

Просто используйте Picasso PlaceHolder

  Picasso.get()
        .load(datas[position].artist?.image)
        .placeholder(R.drawable.music_image)
        .error(R.drawable.music_image)
        .into(holder.cardViewImage)

Я заставил это работать следующим образом:

  1. Создал drawable (найден где-то в интернете) и поместил его в 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. В мой элемент для GridView добавлен элемент 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. В Adapter добавлен Target Object со следующими параметрами, где poster и spinner являются ссылками на ImageView и ProgressBar:

    // Цель показать / скрыть ProgressBar в 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. Результаты будут такими же при загрузке - круг вращается (извините за скриншот, но изображения появляются слишком быстро): ScreenShot

Ответ @DBragion был отличным. Проблема с ним (как и многие другие, упомянутые в комментариях) заключалась в том, что он не давал возможности указать высоту / ширину индикатора выполнения. Ниже приведена измененная версия его ответа с комбинацией ответа @AkankshaRathod.

loading_indicator.png

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
            android:drawable="@drawable/loading_indicator"
            android:pivotX="50%"
            android:pivotY="50%" />
    </item>
</layer-list>

CardView (или любой макет контейнера), содержащий ваш ImageView

       <androidx.cardview.widget.CardView
    android:id="@+id/vCategoryItem"
    android:layout_width="wrap_content"
    android:layout_height="@dimen/height_category_image"
    android:layout_marginLeft="@dimen/smaller"
    app:cardCornerRadius="@dimen/small">

    <ImageView
        android:id="@+id/imgCategoryImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        android:src="@drawable/demo" />

    <ImageView
        android:id="@+id/loadingIndicator"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_gravity="center"
        android:layout_centerInParent="true"
        android:src="@drawable/progress_animation" />

    <TextView
        android:id="@+id/lblCategoryName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom"
        android:layout_marginBottom="@dimen/big"
        android:ellipsize="marquee"
        android:gravity="center"
        android:paddingLeft="@dimen/big"
        android:paddingRight="@dimen/big"
        android:singleLine="true"
        android:text="Category Name"
        android:textColor="@android:color/white"
        android:textSize="15sp"
        android:textStyle="bold" />

</androidx.cardview.widget.CardView>

Загрузка Пикассо:

       Picasso.get().load(yourImageURL).into(imgCategoryImage, new Callback() {
    @Override
    public void onSuccess() {
        loadingIndicator.setVisibility(View.GONE);
    }

    @Override
    public void onError(Exception e) {

    }
});

В этой ссылке Джейк Уортон сказал:

Нету. Мы используем Android BitmapFactory для декодирования всех изображений, и у него нет анимированной поддержки GIF (к сожалению).

Тогда ты не можешь

Для тех, кто пытается использовать технику DBragion: убедитесь, что у вас последняя версия Picasso, иначе она не будет вращаться. Мой не работал, пока я не использовал версию 2.5.2.

compile 'com.squareup.picasso:picasso:2.5.2'
Другие вопросы по тегам