package skin.support.widget;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Shader;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
import android.support.v4.graphics.drawable.DrawableWrapper;
import android.support.v7.widget.TintTypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.ProgressBar;
import skin.support.R;
import skin.support.content.res.SkinCompatResources;
/**
* Created by ximsfei on 2017/1/20.
*/
public class SkinCompatProgressBarHelper extends SkinCompatHelper {
private static final int[] TINT_ATTRS = {
android.R.attr.indeterminateDrawable,
android.R.attr.progressDrawable
};
private final ProgressBar mView;
private Bitmap mSampleTile;
private int mIndeterminateDrawableResId = INVALID_ID;
private int mProgressDrawableResId = INVALID_ID;
SkinCompatProgressBarHelper(ProgressBar view) {
mView = view;
}
void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,
TINT_ATTRS, defStyleAttr, 0);
mIndeterminateDrawableResId = a.getResourceId(0, INVALID_ID);
mProgressDrawableResId = a.getResourceId(1, INVALID_ID);
a.recycle();
applySkin();
}
/**
* Converts a drawable to a tiled version of itself. It will recursively
* traverse layer and state list drawables.
*/
private Drawable tileify(Drawable drawable, boolean clip) {
if (drawable instanceof DrawableWrapper) {
Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
if (inner != null) {
inner = tileify(inner, clip);
((DrawableWrapper) drawable).setWrappedDrawable(inner);
}
} else if (drawable instanceof LayerDrawable) {
LayerDrawable background = (LayerDrawable) drawable;
final int N = background.getNumberOfLayers();
Drawable[] outDrawables = new Drawable[N];
for (int i = 0; i < N; i++) {
int id = background.getId(i);
outDrawables[i] = tileify(background.getDrawable(i),
(id == android.R.id.progress || id == android.R.id.secondaryProgress));
}
LayerDrawable newBg = new LayerDrawable(outDrawables);
for (int i = 0; i < N; i++) {
newBg.setId(i, background.getId(i));
}
return newBg;
} else if (drawable instanceof BitmapDrawable) {
final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
final Bitmap tileBitmap = bitmapDrawable.getBitmap();
if (mSampleTile == null) {
mSampleTile = tileBitmap;
}
final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
shapeDrawable.getPaint().setShader(bitmapShader);
shapeDrawable.getPaint().setColorFilter(bitmapDrawable.getPaint().getColorFilter());
return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
ClipDrawable.HORIZONTAL) : shapeDrawable;
}
return drawable;
}
/**
* Convert a AnimationDrawable for use as a barberpole animation.
* Each frame of the animation is wrapped in a ClipDrawable and
* given a tiling BitmapShader.
*/
private Drawable tileifyIndeterminate(Drawable drawable) {
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), true);
frame.setLevel(10000);
newBg.addFrame(frame, background.getDuration(i));
}
newBg.setLevel(10000);
drawable = newBg;
}
return drawable;
}
private Shape getDrawableShape() {
final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5};
return new RoundRectShape(roundedCorners, null, null);
}
@Override
public void applySkin() {
mIndeterminateDrawableResId = checkResourceId(mIndeterminateDrawableResId);
if (mIndeterminateDrawableResId != INVALID_ID) {
Drawable drawable = SkinCompatResources.getInstance().getDrawable(mIndeterminateDrawableResId);
drawable.setBounds(mView.getIndeterminateDrawable().getBounds());
mView.setIndeterminateDrawable(tileifyIndeterminate(drawable));
}
mProgressDrawableResId = checkProgressDrawableResId(mProgressDrawableResId);
if (mProgressDrawableResId != INVALID_ID) {
Drawable drawable = SkinCompatResources.getInstance().getDrawable(mProgressDrawableResId);
mView.setProgressDrawable(tileify(drawable, false));
}
}
private int checkProgressDrawableResId(int mProgressDrawableResId) {
if (mProgressDrawableResId == R.drawable.abc_ratingbar_material) {
return INVALID_ID;
}
return checkResourceId(mProgressDrawableResId);
}
}