package com.goka.blurredgridmenu; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.support.v8.renderscript.Allocation; import android.support.v8.renderscript.Element; import android.support.v8.renderscript.RenderScript; import android.support.v8.renderscript.ScriptIntrinsicBlur; import android.util.AttributeSet; import android.view.View; // Reference LICENSE -> https://github.com/500px/500px-android-blur/blob/master/LICENSE.txt // Modified by gotokatsuya /** * A custom view for presenting a dynamically blurred version of another view's content. * <p/> * Use {@link #setBlurredView(android.view.View)} to set up the reference to the view to be blurred. * After that, call {@link #invalidate()} to trigger blurring whenever necessary. */ public class BlurringView extends View { private int mDownsampleFactor; private int mOverlayColor; private View mBlurredView; private int mBlurredViewWidth, mBlurredViewHeight; private boolean mDownsampleFactorChanged; private Bitmap mBitmapToBlur, mBlurredBitmap; private Canvas mBlurringCanvas; private RenderScript mRenderScript; private ScriptIntrinsicBlur mBlurScript; private Allocation mBlurInput, mBlurOutput; public BlurringView(Context context) { this(context, null); } public BlurringView(Context context, AttributeSet attrs) { super(context, attrs); initializeRenderScript(context); setBlurRadius(BlurredGridMenuConfig.BLUR_RADIUS); setDownsampleFactor(BlurredGridMenuConfig.DOWNSAMPLE_FACTOR); setOverlayColor(BlurredGridMenuConfig.OVERLAY_COLOR); } public void setBlurredView(View blurredView) { mBlurredView = blurredView; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mBlurredView != null) { if (prepare()) { if (mBlurredView.getBackground() != null && mBlurredView.getBackground() instanceof ColorDrawable) { mBitmapToBlur.eraseColor(((ColorDrawable) mBlurredView.getBackground()).getColor()); } else { mBitmapToBlur.eraseColor(Color.TRANSPARENT); } mBlurredView.draw(mBlurringCanvas); blur(); canvas.save(); canvas.translate(mBlurredView.getX() - getX(), mBlurredView.getY() - getY()); canvas.scale(mDownsampleFactor, mDownsampleFactor); canvas.drawBitmap(mBlurredBitmap, 0, 0, null); canvas.restore(); } canvas.drawColor(mOverlayColor); } } public void setBlurRadius(int radius) { mBlurScript.setRadius(radius); } public void setDownsampleFactor(int factor) { if (factor <= 0) { throw new IllegalArgumentException("Downsample factor must be greater than 0."); } if (mDownsampleFactor != factor) { mDownsampleFactor = factor; mDownsampleFactorChanged = true; } } public void setOverlayColor(int color) { mOverlayColor = color; } private void initializeRenderScript(Context context) { mRenderScript = RenderScript.create(context); mBlurScript = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript)); } protected boolean prepare() { final int width = mBlurredView.getWidth(); final int height = mBlurredView.getHeight(); if (mBlurringCanvas == null || mDownsampleFactorChanged || mBlurredViewWidth != width || mBlurredViewHeight != height) { mDownsampleFactorChanged = false; mBlurredViewWidth = width; mBlurredViewHeight = height; int scaledWidth = width / mDownsampleFactor; int scaledHeight = height / mDownsampleFactor; scaledWidth = scaledWidth - scaledWidth % 4 + 4; scaledHeight = scaledHeight - scaledHeight % 4 + 4; if (mBlurredBitmap == null || mBlurredBitmap.getWidth() != scaledWidth || mBlurredBitmap.getHeight() != scaledHeight) { mBitmapToBlur = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); if (mBitmapToBlur == null) { return false; } mBlurredBitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); if (mBlurredBitmap == null) { return false; } } mBlurringCanvas = new Canvas(mBitmapToBlur); mBlurringCanvas.scale(1f / mDownsampleFactor, 1f / mDownsampleFactor); mBlurInput = Allocation.createFromBitmap(mRenderScript, mBitmapToBlur, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType()); } return true; } protected void blur() { mBlurInput.copyFrom(mBitmapToBlur); mBlurScript.setInput(mBlurInput); mBlurScript.forEach(mBlurOutput); mBlurOutput.copyTo(mBlurredBitmap); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mRenderScript != null) { mRenderScript.destroy(); } } }