Анимированная загрузка изображения в 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
/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)
Я думаю, есть два ключевых момента.
используйте noFade()
установите 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)
Я заставил это работать следующим образом:
Создал 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>
В мой элемент для 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"/>
В 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); } };
Результаты будут такими же при загрузке - круг вращается (извините за скриншот, но изображения появляются слишком быстро): ScreenShot
Ответ @DBragion был отличным. Проблема с ним (как и многие другие, упомянутые в комментариях) заключалась в том, что он не давал возможности указать высоту / ширину индикатора выполнения. Ниже приведена измененная версия его ответа с комбинацией ответа @AkankshaRathod.
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'