java - programacion - Modificando la imagen de recursos de la barra de progreso
manual de programacion android pdf (3)
Generalmente tienes 2 opciones :
1. Como ya se mencionó, use una animation-list
y simplemente intercambie imágenes.
Esta es probablemente la solución más fácil, ya que pueden ser animadas relativamente fácilmente con AnimationDrawable . El único inconveniente sería que necesita al menos 16 imágenes (en todas las resoluciones) para su resultado dado.
2. Usa un dibujo personalizable.
Este es el enfoque más complicado. Tendrá que hacer el dibujo y la animación usted mismo, que es una tarea difícil para la mayoría de las personas con poca buena documentación.
Por lo tanto, tiene que extends Drawable implements Runnable, Animatable
y suministrar algunas buenas implementaciones.
Lo siguiente es una impulsión básica, calculando las posiciones una vez y luego dibujándolas. La animación (el tamaño de los círculos individuales) puede y debe ajustarse aún más;)
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;
}
}
Usar con
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress);
progressBar.setIndeterminateDrawable(new RectProgressDrawable());
progressBar.setIndeterminate(true);
Alternativamente, puede ver el código fuente completo en un proyecto de trabajo here
Quiero crear una barra de progreso para Android. Tengo cuatro imágenes para mi barra de progreso de forma cuadrada.
Estoy usando la barra de progreso definida de Android:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Small"
android:layout_marginRight="5dp" />
Pero si quiero hacer un cuadrado en lugar del círculo, ¿cómo puedo hacerlo? ¿Cómo paso mis 4 imágenes a la barra de progreso?
ejemplo:
Lo estoy haciendo con un montón de imágenes y 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" />
Y 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>
Donde cada imagen loading_progress_indicator_XX
es un indicador de estado de progreso.
La vista personalizada con indicador:
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);
}
}
}
Como resultado, en mi caso se parece a:
Por lo tanto, todo lo que necesitará son los estados de su indicador y vista personalizada como la que se muestra arriba.
Para obtener los estados de su indicador, puede convertir gif
a la lista de png
s que sugiero que usen el servicio EzGif :
Otra opción: puede reutilizar una de las docenas de implementaciones personalizadas del indicador de carga como esta (tiene algunos lo suficientemente cerca de sus indicadores) o esta (aunque, la mayoría de los indicadores de código abierto son circulares).
Espero que ayude.
Sí, necesita crear una vista personalizada para esto, pero hay una biblioteca de Android adicional que podría ser útil para usted.
Por favor, consulte: https://github.com/mrwonderman/android-square-progressbar
Ejemplos de uso de esta biblioteca:
Compruebe también esto: ¿Cómo hacer una barra de progreso cuadrada con cambio de color en cierto intervalo de tiempo?
Aquí encontrará cómo crear su propia implementación de esta biblioteca.
Espero te ayude