Android Drawableツールクラス
package com.skx.tomike.util;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.graphics.drawable.DrawableCompat;
/**
* Drawable
*
* @author shiguotao
*/
public class SkxDrawableUtil {
//----------------------------------------------- Drawable start -----------------------------------------------------------------
/**
* Drawable
*
* @param drawable Drawable
* @param color
* @return Drawable
*/
public static Drawable tintDrawable(@NonNull Drawable drawable, int color) {
// drawable
Drawable wrappedDrawable = getCanTintDrawable(drawable);
// drawable
DrawableCompat.setTint(wrappedDrawable, color);
return wrappedDrawable;
}
/**
* Drawable
*
* @param drawable Drawable
* @param colors
* @return Drawable
*/
public static Drawable tintListDrawable(@NonNull Drawable drawable, ColorStateList colors) {
Drawable wrappedDrawable = getCanTintDrawable(drawable);
// drawable
DrawableCompat.setTintList(wrappedDrawable, colors);
return wrappedDrawable;
}
/**
* tint Drawable
*
* drawable newDrawable()
* warp()
* mutate()
*
* @param drawable drawable
* @return drawable
*/
@NonNull
private static Drawable getCanTintDrawable(@NonNull Drawable drawable) {
// drawable
Drawable.ConstantState state = drawable.getConstantState();
// drawable 、 、
return DrawableCompat.wrap(state == null ? drawable : state.newDrawable()).mutate();
}
//------------------------------------------------ Drawable end -----------------------------------------------------------------
//----------------------------------------------------- Drawable start-----------------------------------------------------------
/**
* Drawable.
* Android xml "selector" StateListDrawable
*
* @param defaultDrawable Drawable
* @param pressedDrawable Drawable
* @return Drawable
*/
public static StateListDrawable getSelectorDrawable(Drawable defaultDrawable, Drawable pressedDrawable) {
if (defaultDrawable == null) return null;
if (pressedDrawable == null) pressedDrawable = defaultDrawable;
int[][] state = {{android.R.attr.state_enabled, -android.R.attr.state_pressed},
{android.R.attr.state_enabled, android.R.attr.state_pressed}};
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(state[0], defaultDrawable);
stateListDrawable.addState(state[1], pressedDrawable);
return stateListDrawable;
}
/**
* Drawable.
* Android xml "selector" StateListDrawable
*
* @param defaultColor
* @param pressedColor
* @param radius
* @return Drawable
*/
public static StateListDrawable getSelectorDrawable(int defaultColor, int pressedColor, float radius) {
Drawable defaultDrawable = new Builder(Builder.RECTANGLE).setColor(defaultColor).setCornerRadius(radius).create();
Drawable pressedDrawable = new Builder(Builder.RECTANGLE).setColor(pressedColor).setCornerRadius(radius).create();
return getSelectorDrawable(defaultDrawable, pressedDrawable);
}
//----------------------------------------------------- Drawable end---------------------------------------------------------------
// --------------------------------------------- -------------------------------------------------
/**
*
*
* @param shape
* @return {@link Builder}
*/
public static Builder getBuilder(int shape) {
return new Builder(shape);
}
/**
* Drawable , ,
*/
public static class Builder {
/**
* Shape is a rectangle, possibly with rounded corners
*/
public static final int RECTANGLE = GradientDrawable.RECTANGLE;
/**
* Shape is an ellipse
*/
public static final int OVAL = GradientDrawable.OVAL;
/**
* Shape is a line
*/
public static final int LINE = GradientDrawable.LINE;
private ColorStateList mSolidColors;
/**
* The color state list of the stroke
*/
private ColorStateList mStrokeColors;
private @ColorInt
int[] mGradientColors;
/**
* The width in pixels of the stroke
*/
private int mStrokeWidth = -1; // if >= 0 use stroking.
/**
* The length in pixels of the dashes, set to 0 to disable dashes
*/
private float mStrokeDashWidth = 0.0f;
/**
* The gap in pixels between dashes
*/
private float mStrokeDashGap = 0.0f;
private float mRadius = 0.0f; // use this if mRadiusArray is null
private float[] mRadiusArray = null;
GradientDrawable mGradientDrawable;
public Builder(int shape) {
mGradientDrawable = new GradientDrawable();
mGradientDrawable.setShape(shape == RECTANGLE || shape == OVAL || shape == LINE ? shape : RECTANGLE);
}
/**
* Sets the colors used to draw the gradient.
*
* Each color is specified as an ARGB integer and the array must contain at
* least 2 colors.
*
* Note: changing colors will affect all instances of a
* drawable loaded from a resource. It is recommended to invoke
* {@link # GradientDrawable.mutate()} before changing the colors.
*
* @param colors an array containing 2 or more ARGB colors
* @see # mutate()
* @see #setColor(int)
*/
public Builder setColors(@Nullable int[] colors) {
this.mGradientColors = colors;
return this;
}
/**
* Changes this drawable to use a single color instead of a gradient.
*
* Note: changing color will affect all instances of a
* drawable loaded from a resource. It is recommended to invoke
* {@link # GradientDrawable.mutate()} before changing the color.
*
* @param argb The color used to fill the shape
*/
public Builder setColor(@ColorInt int argb) {
this.mSolidColors = ColorStateList.valueOf(argb);
return this;
}
/**
* Changes this drawable to use a single color state list instead of a
* gradient. Calling this method with a null argument will clear the color
* and is equivalent to calling {@link #setColor(int)} with the argument
* {@link Color#TRANSPARENT}.
*
* Note: changing color will affect all instances of a
* drawable loaded from a resource. It is recommended to invoke
* {@link # GradientDrawable.mutate()()} before changing the color.
*
* @param colorStateList The color state list used to fill the shape
*/
public Builder setColor(@Nullable ColorStateList colorStateList) {
this.mSolidColors = colorStateList;
return this;
}
/**
* Set the stroke width and color for the drawable. If width is zero,
* then no stroke is drawn.
* Note: changing this property will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
* {@link # mutate()} before changing this property.
*
* @param width The width in pixels of the stroke
* @param color The color of the stroke
* @see # mutate()
* @see #setStroke(int, int, float, float)
*/
public Builder setStroke(int width, @ColorInt int color) {
this.mStrokeWidth = width;
this.mStrokeColors = ColorStateList.valueOf(color);
return this;
}
/**
* Set the stroke width and color state list for the drawable. If width
* is zero, then no stroke is drawn.
* Note: changing this property will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
* {@link # mutate()} before changing this property.
*
* @param width The width in pixels of the stroke
* @param colorStateList The color state list of the stroke
* @see #setStroke(int, ColorStateList, float, float)
*/
public Builder setStroke(int width, ColorStateList colorStateList) {
this.mStrokeWidth = width;
this.mStrokeColors = colorStateList;
return this;
}
/**
* Set the stroke width and color for the drawable. If width is zero,
* then no stroke is drawn. This method can also be used to dash the stroke.
* Note: changing this property will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
* {@link # mutate()} before changing this property.
*
* @param width The width in pixels of the stroke
* @param color The color of the stroke
* @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
* @param dashGap The gap in pixels between dashes
* @see #setStroke(int, int)
*/
public Builder setStroke(int width, @ColorInt int color, float dashWidth, float dashGap) {
this.mStrokeWidth = width;
this.mStrokeColors = ColorStateList.valueOf(color);
this.mStrokeDashWidth = dashWidth;
this.mStrokeDashGap = dashGap;
return this;
}
/**
* Set the stroke width and color state list for the drawable. If width
* is zero, then no stroke is drawn. This method can also be used to dash
* the stroke.
* Note: changing this property will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
* {@link # mutate()} before changing this property.
*
* @param width The width in pixels of the stroke
* @param colorStateList The color state list of the stroke
* @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
* @param dashGap The gap in pixels between dashes
* @see #setStroke(int, ColorStateList)
*/
public Builder setStroke(int width, ColorStateList colorStateList, float dashWidth, float dashGap) {
this.mStrokeWidth = width;
this.mStrokeColors = colorStateList;
this.mStrokeDashWidth = dashWidth;
this.mStrokeDashGap = dashGap;
return this;
}
public Builder setCornerRadius(float radius) {
if (radius < 0) {
radius = 0;
}
this.mRadius = radius;
this.mRadiusArray = null;
return this;
}
/**
* Specifies radii for each of the 4 corners. For each corner, the array
* contains 2 values, [X_radius, Y_radius]
. The corners are
* ordered top-left, top-right, bottom-right, bottom-left. This property
* is honored only when the shape is of type {@link #RECTANGLE}.
*
* Note: changing this property will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
* {@link # mutate()} before changing this property.
*
* @param radii an array of length >= 8 containing 4 pairs of X and Y
* radius for each corner, specified in pixels
* @see #setCornerRadius(float)
*/
public Builder setCornerRadii(@Nullable float[] radii) {
this.mRadiusArray = radii;
if (radii == null) {
this.mRadius = 0;
}
return this;
}
public Drawable create() {
if (mRadiusArray != null) {
mGradientDrawable.setCornerRadii(mRadiusArray);
} else if (mRadius > 0.0f) {
mGradientDrawable.setCornerRadius(mRadius);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mGradientDrawable.setColor(mSolidColors);
// , dashWith, dashGap, dashGap=0dp ,
mGradientDrawable.setStroke(mStrokeWidth, mStrokeColors, mStrokeDashWidth, mStrokeDashGap);
} else {
mGradientDrawable.setColor(mSolidColors.getDefaultColor());
// , dashWith, dashGap, dashGap=0dp ,
mGradientDrawable.setStroke(mStrokeWidth, mStrokeColors.getDefaultColor(), mStrokeDashWidth, mStrokeDashGap);
}
return mGradientDrawable;
}
}
}