package com.marshalchen.common.uimodule.foldablelayout.shading; import android.content.Context; import android.graphics.*; import android.view.Gravity; public class GlanceFoldShading implements FoldShading { private static final int SHADOW_COLOR = Color.BLACK; private static final int SHADOW_MAX_ALPHA = 192; private final Paint mSolidShadow; private final Paint mGlancePaint; private final Bitmap mGlance; private final Rect mGlanceFrom; private final Rect mGlanceTo; public GlanceFoldShading(Context context, Bitmap glance) { mSolidShadow = new Paint(); mSolidShadow.setColor(SHADOW_COLOR); mGlance = glance; mGlancePaint = new Paint(); mGlancePaint.setDither(true); mGlancePaint.setFilterBitmap(true); mGlanceFrom = new Rect(); mGlanceTo = new Rect(); } @Override public void onPreDraw(Canvas canvas, Rect bounds, float rotation, int gravity) { // NO-OP } @Override public void onPostDraw(Canvas canvas, Rect bounds, float rotation, int gravity) { float intencity = getShadowIntencity(rotation, gravity); if (intencity > 0) { int alpha = (int) (SHADOW_MAX_ALPHA * intencity); mSolidShadow.setAlpha(alpha); canvas.drawRect(bounds, mSolidShadow); } boolean isDrawGlance = computeGlance(bounds, rotation, gravity); if (isDrawGlance) { canvas.drawBitmap(mGlance, mGlanceFrom, mGlanceTo, mGlancePaint); } } private float getShadowIntencity(float rotation, int gravity) { float intencity = 0; if (gravity == Gravity.TOP) { if (rotation > -90 && rotation < 0) { // (-90; 0) - rotation is applied intencity = -rotation / 90f; } } return intencity; } private boolean computeGlance(Rect bounds, float rotation, int gravity) { if (gravity == Gravity.BOTTOM) { if (rotation > 0 && rotation < 90) { // (0; 90) - rotation is applied final float aspect = (float) mGlance.getWidth() / (float) bounds.width(); // computing glance offset final int distance = (int) (bounds.height() * ((rotation - 60f) / 15f)); final int distanceOnGlance = (int) (distance * aspect); // computing "to" bounds int scaledGlanceHeight = (int) (mGlance.getHeight() / aspect); mGlanceTo.set(bounds.left, bounds.top + distance, bounds.right, bounds.top + distance + scaledGlanceHeight); if (!mGlanceTo.intersect(bounds)) { // glance is not visible return false; } // computing "from" bounds int scaledBoundsHeight = (int) (bounds.height() * aspect); mGlanceFrom.set(0, -distanceOnGlance, mGlance.getWidth(), -distanceOnGlance + scaledBoundsHeight); if (!mGlanceFrom.intersect(0, 0, mGlance.getWidth(), mGlance.getHeight())) { // glance is not visible, should not happen due to previouse check return false; } return true; } } return false; } }