Android Drawableツールクラス


-Drawableシェーディング-Drawableフィレット長方形-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; } } }