Изменение изображения ресурса панели выполнения

Я хочу создать индикатор прогресса для Android. У меня есть четыре изображения для моего квадратного индикатора хода.

Я использую определенный индикатор прогресса Android:

<ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Small" android:layout_marginRight="5dp" /> 

Но если я хочу сделать квадрат вместо круга, как я могу это сделать? Как передать 4 изображения на индикатор выполнения?

пример:

Введите описание изображения здесь

Solutions Collecting From Web of "Изменение изображения ресурса панели выполнения"

Обычно у вас есть 2 варианта :

1. Как уже упоминалось, используйте animation-list и просто поменяйте фотографии.

Это, вероятно, более легкое решение, поскольку они могут относительно легко быть анимированными с AnimationDrawable . Единственным недостатком будет то, что для вашего заданного результата вам понадобится как минимум 16 изображений (во всех разрешениях).

2. Используйте пользовательский вариант.

Это более сложный подход. Вам нужно будет сделать рисунок и оживить себя, что является трудной задачей для большинства людей с небольшой хорошей документацией.

Поэтому вам необходимо extends Drawable implements Runnable, Animatable и предоставить некоторые хорошие реализации.

Ниже приводится базовое движение, вычисление позиций один раз, а затем их рисование. Анимация (размер отдельных кругов) может и должна быть дополнительно изменена;)

Результат в 3 вариантах:
Progree Bars

 public class RectProgressDrawable extends Drawable implements Runnable, Animatable { private static final long FRAME_DELAY = 1000 / 60; private static final String TAG = "RectProgressDrawable"; private boolean mRunning = false; private long mStartTime; private int mDuration = 1000; private Paint mPaint; private float[] posX; private float[] posY; private float mSize; private int mPoints = 5; /** * The padding in px. */ private int mPadding = 4; private int mAnimatedPoints = 5; public void setPoints(int points) { if (points != mPoints) { mPoints = points; init(); } } private void init() { if (mPaint == null) { mPaint = new Paint(); mPaint.setColor(Color.WHITE); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); } posX = new float[(mPoints - 1) * 4]; posY = new float[(mPoints - 1) * 4]; Rect bounds = new Rect(); bounds.set(getBounds()); bounds.inset(mPadding, mPadding); float cellWidth = ((float) bounds.width()) / ((float) mPoints); float cellHeight = ((float) bounds.height()) / ((float) mPoints); float min = Math.min(cellWidth, cellHeight); mSize = min / (mPoints - 1); for (int i = 0; i < mPoints; i++) { // top row posX[i] = bounds.left + cellWidth * (float) i + cellWidth / 2; posY[i] = bounds.top + cellHeight / 2; } for (int i = 0; i < mPoints - 2; i++) { // sides // right side top bottom posX[mPoints + i] = bounds.left + cellWidth * (mPoints - 1) + cellWidth / 2; posY[mPoints + i] = bounds.top + cellHeight * (i + 1) + cellHeight / 2; //left side bottom top posX[3 * mPoints - 2 + i] = bounds.left + cellWidth / 2; posY[3 * mPoints - 2 + i] = bounds.top + cellHeight * (mPoints - 2 - i) + cellHeight / 2; } for (int i = 0; i < mPoints; i++) { // bottom from right to left posX[2 * mPoints - 2 + i] = bounds.left + cellWidth * (mPoints - 1 - i) + cellWidth / 2; posY[2 * mPoints - 2 + i] = bounds.top + cellHeight * (mPoints - 1) + cellHeight / 2; } } @Override public void draw(Canvas canvas) { if (isRunning()) { // animation in progress final int save = canvas.save(); long timeDiff = SystemClock.uptimeMillis() - mStartTime; float progress = ((float) timeDiff) / ((float) mDuration); // 0..1 int level = ((int) (progress * posX.length)) % posX.length; // current value 0..posX.length for (int i = 0; i < posX.length; i++) { if ((i >= level && i < level + mAnimatedPoints) || level + mAnimatedPoints > posX.length && i < (level + mAnimatedPoints) % posX.length) { float num = (i - level + posX.length) % posX.length; // 0..5 float size = mSize * (1 + (num * (1f / mAnimatedPoints))); float sizeNext = mSize * (1 + ((num + 1) * (1f / mAnimatedPoints))); float levelProgress = progress * posX.length - (int) (progress * posX.length); float currentSize; if (num == (mAnimatedPoints - 1)) { // grow to next size currentSize = mSize + (size - mSize) * levelProgress; } else { // shrink currentSize = size + (sizeNext - size) * (1 - levelProgress); } canvas.drawCircle(posX[i], posY[i], currentSize, mPaint); } else { canvas.drawCircle(posX[i], posY[i], mSize, mPaint); } } canvas.restoreToCount(save); } else { // draw normal for (int i = 0; i < posX.length; i++) { canvas.drawCircle(posX[i], posY[i], mSize, mPaint); } } } @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); init(); } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter colorFilter) { } @Override public int getOpacity() { return 0; } @Override public void start() { if (mRunning) stop(); mRunning = true; mStartTime = SystemClock.uptimeMillis(); invalidateSelf(); scheduleSelf(this, SystemClock.uptimeMillis() + FRAME_DELAY); } @Override public void stop() { unscheduleSelf(this); mRunning = false; } @Override public boolean isRunning() { return mRunning; } @Override public void run() { invalidateSelf(); long uptimeMillis = SystemClock.uptimeMillis(); if (uptimeMillis + FRAME_DELAY < mStartTime + mDuration) { scheduleSelf(this, uptimeMillis + FRAME_DELAY); } else { mRunning = false; start(); } } public void setAnimatedPoints(int animatedPoints) { mAnimatedPoints = animatedPoints; } } 

Использовать с

  ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress); progressBar.setIndeterminateDrawable(new RectProgressDrawable()); progressBar.setIndeterminate(true); 

Кроме того, вы можете увидеть полный исходный код в рабочем проекте здесь

Я делаю это с кучей изображений и animation-list :

 <?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/loadingAnimationImageView" android:layout_width="36dp" android:layout_height="36dp" android:background="@drawable/loading_progress_indicator_animation" /> 

И res\drawable\loading_progres_indicator_animation.xml :

 <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/selected" android:oneshot="false"> <item android:drawable="@drawable/loading_progress_indicator_0" android:duration="40" /> <item android:drawable="@drawable/loading_progress_indicator_1" android:duration="40" /> <item android:drawable="@drawable/loading_progress_indicator_2" android:duration="40" /> ..... <item android:drawable="@drawable/loading_progress_indicator_11" android:duration="40" /> <item android:drawable="@drawable/loading_progress_indicator_12" android:duration="40" /> </animation-list> 

Где каждый файл loading_progress_indicator_XX является индикатором состояния прогресса.

Пользовательский вид с индикатором:

 public final class LoadingAnimationView extends FrameLayout { ImageView loadingAnimationImageView; AnimationDrawable loadingProgressAnimation; Handler handler = new Handler(Looper.getMainLooper()); public LoadingAnimationView(Context context) { super(context); initialize(); } private void initialize() { LayoutInflater.from(getContext()).inflate(R.layout.view_loading_videoview, this); loadingAnimationImageView = (ImageView)getView().findViewById(R.id.loadingAnimationImageView); loadingProgressAnimation = (AnimationDrawable) loadingAnimationImageView.getBackground(); adaptToVisibility(getVisibility()); } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); adaptToVisibility(visibility); } void adaptToVisibility(final int visibility) { if (visibility == VISIBLE) { loadingProgressAnimation.start(); //This is to avoid "blinking" of progress indicator (if page is loading from cache) handler.postDelayed(new Runnable() { @Override public void run() { loadingAnimationImageView.setVisibility(visibility); } }, 200); } else { loadingProgressAnimation.stop(); loadingAnimationImageView.setVisibility(visibility); } } } 

В результате в моем случае это выглядит так:

Введите описание изображения здесь

Таким образом, все, что вам понадобится, – это состояние вашего индикатора и пользовательского представления, как показано выше.

Чтобы получить состояние вашего индикатора, вы можете преобразовать gif в список png s. Я бы предложил использовать службу EzGif :

Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь

Другой вариант – вы можете повторно использовать одну из десятков пользовательских реализаций индикатора загрузки, подобную этой (она достаточно близко к вашим индикаторам) или эта (хотя большинство индикаторов с открытым исходным кодом являются круговыми).

Я надеюсь, что это помогает.

Да, для этого вам нужно создать собственное представление, но есть дополнительная библиотека Android, которая может быть вам полезна.

Проверьте: https://github.com/mrwonderman/android-square-progressbar

Примеры использования этой библиотеки:

Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь Введите описание изображения здесь

Проверьте также это: Как сделать квадрат прогресса с изменяющимся цветом в определенный промежуток времени?

Здесь вы найдете, как создать свою собственную реализацию этой библиотеки.

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