Android模糊视图(视图背后的模糊背景)

我试图让图像模糊的底部成为顶部的视图,就像在图像中一样。

我尝试使用Rendenscript模糊它,但我不能只模糊视图背后的部分。 🙁

我见过很多库,但几乎所有库都模糊了整个图像,但不是它的一部分。

另外,一个重要的部分是我在ViewPager中使用它,因此在IOS中需要像这样快速和动态的东西,它在它背后的图像改变时重绘自己。

任何帮助表示赞赏。 谢谢你的到来!

我的xml:

     

我的代码:

BlurBuilder.java

 public class BlurBuilder { private static final float BITMAP_SCALE = 0.1f; private static final float BLUR_RADIUS = 7.5f; public static Bitmap blur(Context context, Bitmap image) { int width = Math.round(image.getWidth() * BITMAP_SCALE); int height = Math.round(image.getHeight() * BITMAP_SCALE); Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false); Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap); RenderScript rs = RenderScript.create(context); ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); theIntrinsic.setRadius(BLUR_RADIUS); theIntrinsic.setInput(tmpIn); theIntrinsic.forEach(tmpOut); tmpOut.copyTo(outputBitmap); return outputBitmap; } @SuppressLint("NewApi") public static void blur(final Context context, final Bitmap bitmap, final View view) { new AsyncTask() { @Override protected Bitmap doInBackground(Void... params) { Paint paint = new Paint(); paint.setFilterBitmap(true); Bitmap cropImage = Bitmap.createBitmap(bitmap, 0, bitmap.getHeight() - view.getHeight(), bitmap.getWidth(), view.getHeight()); return BlurBuilder.blur(context, cropImage); } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); if (bitmap != null) { int sdk = android.os.Build.VERSION.SDK_INT; if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) { view.setBackgroundDrawable(new BitmapDrawable(context.getResources(), bitmap)); } else { view.setBackground(new BitmapDrawable(context.getResources(), bitmap)); } } } }.execute(); } } 

在我的MainActivity的onCreate中,我做了:

 BlurBuilder.blur(BitmapActivity.this, ((BitmapDrawable) mView.getDrawable()).getBitmap(), mDummyView); 

结果如下:

在此处输入图像描述

将这两个类添加到您的应用中,

1> BlurKit.Java

 public class BlurKit { private static BlurKit instance; private RenderScript rs; public static void init(Context context) { if (instance != null) { return; } instance = new BlurKit(); instance.rs = RenderScript.create(context); } public Bitmap blur(Bitmap src, int radius) { final Allocation input = Allocation.createFromBitmap(rs, src); final Allocation output = Allocation.createTyped(rs, input.getType()); final ScriptIntrinsicBlur script; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); script.setRadius(radius); script.setInput(input); script.forEach(output); } output.copyTo(src); return src; } public Bitmap blur(View src, int radius) { Bitmap bitmap = getBitmapForView(src, 1f); return blur(bitmap, radius); } public Bitmap fastBlur(View src, int radius, float downscaleFactor) { Bitmap bitmap = getBitmapForView(src, downscaleFactor); return blur(bitmap, radius); } private Bitmap getBitmapForView(View src, float downscaleFactor) { Bitmap bitmap = Bitmap.createBitmap( (int) (src.getWidth() * downscaleFactor), (int) (src.getHeight() * downscaleFactor), Bitmap.Config.ARGB_4444 ); Canvas canvas = new Canvas(bitmap); Matrix matrix = new Matrix(); matrix.preScale(downscaleFactor, downscaleFactor); canvas.setMatrix(matrix); src.draw(canvas); return bitmap; } public static BlurKit getInstance() { if (instance == null) { throw new RuntimeException("BlurKit not initialized!"); } return instance; } } 

2> BlurLayout.Java

 public class BlurLayout extends FrameLayout { public static final float DEFAULT_DOWNSCALE_FACTOR = 0.12f; public static final int DEFAULT_BLUR_RADIUS = 12; public static final int DEFAULT_FPS = 60; // Customizable attributes /** Factor to scale the view bitmap with before blurring. */ private float mDownscaleFactor; /** Blur radius passed directly to stackblur library. */ private int mBlurRadius; /** Number of blur invalidations to do per second. */ private int mFPS; // Calculated class dependencies /** Reference to View for top-parent. For retrieval see {@link #getActivityView() getActivityView}. */ private WeakReference mActivityView; public BlurLayout(Context context) { super(context, null); } public BlurLayout(Context context, AttributeSet attrs) { super(context, attrs); BlurKit.init(context); TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.BlurLayout, 0, 0); try { mDownscaleFactor = a.getFloat(R.styleable.BlurLayout_downscaleFactor, DEFAULT_DOWNSCALE_FACTOR); mBlurRadius = a.getInteger(R.styleable.BlurLayout_blurRadius, DEFAULT_BLUR_RADIUS); mFPS = a.getInteger(R.styleable.BlurLayout_fps, DEFAULT_FPS); } finally { a.recycle(); } if (mFPS > 0) { Choreographer.getInstance().postFrameCallback(invalidationLoop); } } /** Choreographer callback that re-draws the blur and schedules another callback. */ private Choreographer.FrameCallback invalidationLoop = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { invalidate(); Choreographer.getInstance().postFrameCallbackDelayed(this, 1000 / mFPS); } }; /** * {@inheritDoc} */ @Override public void invalidate() { super.invalidate(); Bitmap bitmap = blur(); if (bitmap != null) { setBackground(new BitmapDrawable(bitmap)); } } /** * Recreates blur for content and sets it as the background. */ private Bitmap blur() { if (getContext() == null) { return null; } // Check the reference to the parent view. // If not available, attempt to make it. if (mActivityView == null || mActivityView.get() == null) { mActivityView = new WeakReference<>(getActivityView()); if (mActivityView.get() == null) { return null; } } // Calculate the relative point to the parent view. Point pointRelativeToActivityView = getPositionInScreen(); // Set alpha to 0 before creating the parent view bitmap. // The blur view shouldn't be visible in the created bitmap. setAlpha(0); // Screen sizes for bound checks int screenWidth = mActivityView.get().getWidth(); int screenHeight = mActivityView.get().getHeight(); // The final dimensions of the blurred bitmap. int width = (int) (getWidth() * mDownscaleFactor); int height = (int) (getHeight() * mDownscaleFactor); // The X/Y position of where to crop the bitmap. int x = (int) (pointRelativeToActivityView.x * mDownscaleFactor); int y = (int) (pointRelativeToActivityView.y * mDownscaleFactor); // Padding to add to crop pre-blur. // Blurring straight to edges has side-effects so padding is added. int xPadding = getWidth() / 8; int yPadding = getHeight() / 8; // Calculate padding independently for each side, checking edges. int leftOffset = -xPadding; leftOffset = x + leftOffset >= 0 ? leftOffset : 0; int rightOffset = xPadding; rightOffset = x + getWidth() + rightOffset <= screenWidth ? rightOffset : screenWidth - getWidth() - x; int topOffset = -yPadding; topOffset = y + topOffset >= 0 ? topOffset : 0; int bottomOffset = yPadding; bottomOffset = y + height + bottomOffset <= screenHeight ? bottomOffset : 0; // Create parent view bitmap, cropped to the BlurLayout area with above padding. Bitmap bitmap; try { bitmap = getDownscaledBitmapForView( mActivityView.get(), new Rect( pointRelativeToActivityView.x + leftOffset, pointRelativeToActivityView.y + topOffset, pointRelativeToActivityView.x + getWidth() + Math.abs(leftOffset) + rightOffset, pointRelativeToActivityView.y + getHeight() + Math.abs(topOffset) + bottomOffset ), mDownscaleFactor ); } catch (NullPointerException e) { return null; } // Blur the bitmap. bitmap = BlurKit.getInstance().blur(bitmap, mBlurRadius); //Crop the bitmap again to remove the padding. bitmap = Bitmap.createBitmap( bitmap, (int) (Math.abs(leftOffset) * mDownscaleFactor), (int) (Math.abs(topOffset) * mDownscaleFactor), width, height ); // Make self visible again. setAlpha(1); // Set background as blurred bitmap. return bitmap; } /** * Casts context to Activity and attempts to create a view reference using the window decor view. * @return View reference for whole activity. */ private View getActivityView() { Activity activity; try { activity = (Activity) getContext(); } catch (ClassCastException e) { return null; } return activity.getWindow().getDecorView().findViewById(android.R.id.content); } /** * Returns the position in screen. Left abstract to allow for specific implementations such as * caching behavior. */ private Point getPositionInScreen() { return getPositionInScreen(this); } /** * Finds the Point of the parent view, and offsets result by self getX() and getY(). * @return Point determining position of the passed in view inside all of its ViewParents. */ private Point getPositionInScreen(View view) { if (getParent() == null) { return new Point(); } ViewGroup parent; try { parent = (ViewGroup) view.getParent(); } catch (Exception e) { return new Point(); } if (parent == null) { return new Point(); } Point point = getPositionInScreen(parent); point.offset((int) view.getX(), (int) view.getY()); return point; } /** * Users a View reference to create a bitmap, and downscales it using the passed in factor. * Uses a Rect to crop the view into the bitmap. * @return Bitmap made from view, downscaled by downscaleFactor. * @throws NullPointerException */ private Bitmap getDownscaledBitmapForView(View view, Rect crop, float downscaleFactor) throws NullPointerException { View screenView = view.getRootView(); int width = (int) (crop.width() * downscaleFactor); int height = (int) (crop.height() * downscaleFactor); if (screenView.getWidth() <= 0 || screenView.getHeight() <= 0 || width <= 0 || height <= 0) { throw new NullPointerException(); } float dx = -crop.left * downscaleFactor; float dy = -crop.top * downscaleFactor; Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); Canvas canvas = new Canvas(bitmap); Matrix matrix = new Matrix(); matrix.preScale(downscaleFactor, downscaleFactor); matrix.postTranslate(dx, dy); canvas.setMatrix(matrix); screenView.draw(canvas); return bitmap; } /** * Sets downscale factor to use pre-blur. * See {@link #mDownscaleFactor}. */ public void setDownscaleFactor(float downscaleFactor) { this.mDownscaleFactor = downscaleFactor; invalidate(); } /** * Sets blur radius to use on downscaled bitmap. * See {@link #mBlurRadius}. */ public void setBlurRadius(int blurRadius) { this.mBlurRadius = blurRadius; invalidate(); } /** * Sets FPS to invalidate blur with. * See {@link #mFPS}. */ public void setFPS(int fps) { this.mFPS = fps; } } 

在XML文件中:

        

不要忘记将其添加到values> attr.xml

        

这可以通过以下步骤实现:

  • 通过裁剪背景图像提取LinearLayout的背景图像。 现在扩展LinearLayout类。

  • 覆盖OnDraw(Canvas mCanvas)方法。

  • 在自定义LinearLayout类中创建两个方法:

    1. DrawBitmap
    2. DrawColor。
  • 首先通过将从ViewPager获得的偏移量提供给背景图像来调用DrawBitmap函数,以便在使用时滑动屏幕移动图像。

  • 最后用透明度级别绘制颜色

我希望这能解决你的问题。

示例代码

如何模糊视图

尝试applyBlur方法:

 private void applyBlur(ImageView image) { image.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { image.getViewTreeObserver().removeOnPreDrawListener(this); image.buildDrawingCache(); Bitmap bmp = image.getDrawingCache(); blur(bmp, text); return true; } }); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) private void blur(Bitmap bkg, View view) { long startMs = System.currentTimeMillis(); float radius = 20; Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth()), (int) (view.getMeasuredHeight()), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(overlay); canvas.translate(-view.getLeft(), -view.getTop()); canvas.drawBitmap(bkg, 0, 0, null); RenderScript rs = RenderScript.create(getActivity()); Allocation overlayAlloc = Allocation.createFromBitmap( rs, overlay); ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create( rs, overlayAlloc.getElement()); blur.setInput(overlayAlloc); blur.setRadius(radius); blur.forEach(overlayAlloc); overlayAlloc.copyTo(overlay); view.setBackground(new BitmapDrawable( getResources(), overlay)); rs.destroy(); }