/* * Copyright 2014 Google Inc. * * 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 com.boardgamegeek.util; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; 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.os.Build; import android.view.Gravity; import android.view.View; import com.boardgamegeek.R; /** * Utility methods for creating prettier gradient scrims. Lovingly borrowed from com.google.android.apps.muzei.util. */ public class ScrimUtils { private ScrimUtils() { } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public static void applyDefaultScrim(View view) { if (view == null) { return; } setBackground(view, ScrimUtils.makeDefaultScrimDrawable(view.getContext())); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public static void applyInvertedScrim(View view) { if (view == null) { return; } setBackground(view, ScrimUtils.makeInvertedScrimDrawable(view.getContext())); } /** * A black scrim that's darkest at the top. */ public static Drawable makeDefaultScrimDrawable(Context context) { //noinspection deprecation return ScrimUtils.makeCubicGradientScrimDrawable(context.getResources().getColor(R.color.black_overlay), 4, Gravity.TOP); } /** * A white scrim that's lightest at the bottom. */ public static Drawable makeInvertedScrimDrawable(Context context) { //noinspection deprecation return ScrimUtils.makeCubicGradientScrimDrawable(context.getResources().getColor(R.color.black_overlay), 3, Gravity.BOTTOM); } /** * Creates an approximated cubic gradient using a multi-stop linear gradient. See * <a href="https://plus.google.com/+RomanNurik/posts/2QvHVFWrHZf">this post</a> for more * details. */ @SuppressLint("RtlHardcoded") public static Drawable makeCubicGradientScrimDrawable(int baseColor, int numStops, int gravity) { numStops = Math.max(numStops, 2); PaintDrawable paintDrawable = new PaintDrawable(); paintDrawable.setShape(new RectShape()); final int[] stopColors = new int[numStops]; 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 < numStops; i++) { float x = i * 1f / (numStops - 1); float opacity = MathUtils.constrain((float) Math.pow(x, 3), 0, 1); stopColors[i] = Color.argb((int) (alpha * opacity), red, green, blue); } final float x0, x1, y0, y1; switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) { case Gravity.LEFT: x0 = 1; x1 = 0; break; case Gravity.RIGHT: 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; } paintDrawable.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); } }); return paintDrawable; } private static void setBackground(View view, Drawable scrim) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.setBackground(scrim); } else { //noinspection deprecation view.setBackgroundDrawable(scrim); } } }