This is how I did it (essentially creating a custom Drawable from program code).
It gets a Drawable, tiles it (repeating it) and crops it to a shape that was provided by the Callable. It handles AnimationDrawable also: creates a similar AnimationDrawable tiling and cropping each frame. For the clip shape I had to use Callable - which is essentially a factory - because a new ShapeDrawable has to be created for each animation frame. The inner class EquallyRoundCornerRect can be used for the most common scenario: equal round corner.
/**
* It gets a {@link android.graphics.drawable.Drawable}, tiles it (repeating it) and crops it to a shape that was provided by the
* {@link java.util.concurrent.Callable}. It handles {@link android.graphics.drawable.AnimationDrawable} also: creates a similar
* {@link android.graphics.drawable.AnimationDrawable} tiling and cropping each frame. For the clip shape I had to use
* {@link java.util.concurrent.Callable} - which is essentially a factory - because a new {@link android.graphics.drawable.ShapeDrawable}
* has to be created for each animation frame.
* The inner class {@link EquallyRoundCornerRect} can be used for the most common scenario: equal round corner.
*/
public class TiledClippedDrawable {
public static Drawable createFrom(final Drawable originalDrawable, final Callable<ShapeDrawable> clipShape) {
return tileifyIndeterminate(originalDrawable, clipShape);
}
private static Drawable tileify(Drawable drawable, final Callable<ShapeDrawable> clipShape) {
final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
try {
final ShapeDrawable shapeDrawable = clipShape.call();
final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
shapeDrawable.getPaint().setShader(bitmapShader);
return new ClipDrawable(shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Drawable tileifyIndeterminate(Drawable drawable, final Callable<ShapeDrawable> clipShape) {
if (drawable instanceof AnimationDrawable) {
AnimationDrawable background = (AnimationDrawable) drawable;
final int N = background.getNumberOfFrames();
AnimationDrawable newBg = new AnimationDrawable();
newBg.setOneShot(background.isOneShot());
for (int i = 0; i < N; i++) {
Drawable frame = tileify(background.getFrame(i), clipShape);
frame.setLevel(10000);
newBg.addFrame(frame, background.getDuration(i));
}
newBg.setLevel(10000);
drawable = newBg;
return drawable;
}
return tileify(drawable, clipShape);
}
public static class EquallyRoundCornerRect implements Callable<ShapeDrawable> {
private final int cornerRadiusPixel;
public EquallyRoundCornerRect(final int cornerRadiusPixel) {
this.cornerRadiusPixel = cornerRadiusPixel;
}
@Override
public ShapeDrawable call() throws Exception {
final float[] roundedCorners = new float[] {cornerRadiusPixel, cornerRadiusPixel, cornerRadiusPixel, cornerRadiusPixel,
cornerRadiusPixel, cornerRadiusPixel, cornerRadiusPixel, cornerRadiusPixel};
return new ShapeDrawable(new RoundRectShape(roundedCorners, null, null));
}
}
}
And this is how it can be used:
final int cornerRadius = getResources().getDimensionPixelOffset(R.dimen.progressbar_corner_radius); final Drawable originalDrawable = getResources().getDrawable(R.drawable.progress_bar_indeterminate_horizontal); final Drawable roundedAnimation = TiledClippedDrawable.createFrom(originalDrawable, new TiledClippedDrawable.EquallyRoundCornerRect(cornerRadius)); unpackingSpinner = (ProgressBar) backView.findViewById(R.id.gallery_item_unpacking_spinner); unpackingSpinner.setIndeterminateDrawable(roundedAnimation);
Here the R.dimen.progressbar_corner_radius is a number, and the R.drawable.progress_bar_indeterminate_horizontal is an animationlist. Each of those install_progressbar_indeterminate1 images contain only a fragment, because they will be tiled anyway.
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/install_progressbar_indeterminate1" android:duration="200" /> <item android:drawable="@drawable/install_progressbar_indeterminate2" android:duration="200" /> <item android:drawable="@drawable/install_progressbar_indeterminate3" android:duration="200" /> </animation-list>

No comments:
Post a Comment