package org.wikipedia.util; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.graphics.drawable.PaintDrawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.RectShape; import android.view.Gravity; public final class GradientUtil { private static final int GRADIENT_NUM_STOPS = 8; private static final int GRADIENT_POWER = 3; public static Drawable getCubicGradient(int baseColor, int gravity) { PaintDrawable drawable = new PaintDrawable(); drawable.setShape(new RectShape()); setCubicGradient(drawable, baseColor, gravity); return drawable; } /** * Create a cubic gradient by using a compound gradient composed of a series of linear * gradients with intermediate color values. * adapted from: https://github.com/romannurik/muzei/blob/master/main/src/main/java/com/google/android/apps/muzei/util/ScrimUtil.java * @param baseColor The color from which the gradient starts (the ending color is transparent). * @param gravity Where the gradient should start from. Note: when making horizontal gradients, * remember to use START/END, instead of LEFT/RIGHT. */ public static void setCubicGradient(PaintDrawable drawable, int baseColor, int gravity) { final int[] stopColors = new int[GRADIENT_NUM_STOPS]; int red = Color.red(baseColor); int green = Color.green(baseColor); int blue = Color.blue(baseColor); int alpha = Color.alpha(baseColor); for (int i = 0; i < GRADIENT_NUM_STOPS; i++) { float x = i * 1f / (GRADIENT_NUM_STOPS - 1); float opacity = MathUtil.constrain((float) Math.pow(x, GRADIENT_POWER), 0.0f, 1.0f); stopColors[i] = Color.argb((int) (alpha * opacity), red, green, blue); } final float x0, x1, y0, y1; switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) { case Gravity.START: x0 = 1; x1 = 0; break; case Gravity.END: x0 = 0; x1 = 1; break; default: x0 = 0; x1 = 0; break; } switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) { case Gravity.TOP: y0 = 1; y1 = 0; break; case Gravity.BOTTOM: y0 = 0; y1 = 1; break; default: y0 = 0; y1 = 0; break; } drawable.setShaderFactory(new ShapeDrawable.ShaderFactory() { @Override public Shader resize(int width, int height) { return new LinearGradient(width * x0, height * y0, width * x1, height * y1, stopColors, null, Shader.TileMode.CLAMP); } }); } private GradientUtil() { } }