166 lines
6 KiB
Java
166 lines
6 KiB
Java
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.support.v7.internal.widget;
|
|
|
|
import android.content.Context;
|
|
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.v4.view.ViewCompat;
|
|
import android.util.AttributeSet;
|
|
import android.view.Gravity;
|
|
import android.widget.RatingBar;
|
|
|
|
/**
|
|
* An tint aware {@link android.widget.RatingBar}.
|
|
* <p>
|
|
* This will automatically be used when you use {@link android.widget.RatingBar} in your
|
|
* layouts. You should only need to manually use this class when writing custom views.
|
|
*/
|
|
public class TintRatingBar extends RatingBar {
|
|
|
|
private static final int[] TINT_ATTRS = {
|
|
android.R.attr.indeterminateDrawable,
|
|
android.R.attr.progressDrawable
|
|
};
|
|
|
|
private Bitmap mSampleTile;
|
|
|
|
public TintRatingBar(Context context) {
|
|
this(context, null);
|
|
}
|
|
|
|
public TintRatingBar(Context context, AttributeSet attrs) {
|
|
this(context, attrs, android.R.attr.ratingBarStyle);
|
|
}
|
|
|
|
public TintRatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
if (TintManager.SHOULD_BE_USED) {
|
|
TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
|
|
TINT_ATTRS, defStyleAttr, 0);
|
|
|
|
Drawable drawable = a.getDrawable(0);
|
|
if (drawable != null) {
|
|
setIndeterminateDrawable(tileifyIndeterminate(drawable));
|
|
}
|
|
|
|
drawable = a.getDrawable(1);
|
|
if (drawable != null) {
|
|
setProgressDrawable(tileify(drawable, false));
|
|
}
|
|
|
|
a.recycle();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 Bitmap tileBitmap = ((BitmapDrawable) drawable).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);
|
|
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
|
|
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
if (mSampleTile != null) {
|
|
final int width = mSampleTile.getWidth() * getNumStars();
|
|
setMeasuredDimension(ViewCompat.resolveSizeAndState(width, widthMeasureSpec, 0),
|
|
getMeasuredHeight());
|
|
}
|
|
}
|
|
|
|
}
|