Android Blur View(模糊视图背后的背景)
Posted
技术标签:
【中文标题】Android Blur View(模糊视图背后的背景)【英文标题】:Android Blur View (Blur background behind the view) 【发布时间】:2015-10-26 20:07:58 【问题描述】:我正在尝试使图像的底部部分模糊,使其顶部的视图像图像中一样。
我尝试使用 Rendenscript 对其进行模糊处理,但我无法仅模糊视图后面的部分。 :(
我见过很多库,但几乎所有的库都模糊了整个图像,而不是其中的一部分。
另外,一个重要的部分是我在 ViewPager 中使用它,因此需要像this in ios 这样的快速和动态的东西,它会在它背后的图像发生变化时重新绘制自己。
感谢任何帮助。感谢您的光临!
我的 xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="@+id/image"
android:src="@drawable/broadstairs"
android:layout_
android:layout_
android:scaleType="centerCrop"
android:layout_centerInParent="true"/>
<TextView
android:id="@+id/text"
android:layout_
android:layout_
android:text="Hello World"
android:gravity="center"
android:layout_alignParentBottom="true"
android:textColor="@android:color/white"
android:textStyle="bold"
android:textSize="36sp"/>
</RelativeLayout>
我的代码:
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<Void, Void, Bitmap>()
@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);
结果如下:
【问题讨论】:
也许你的底视图上的透明模糊可以解决问题。 @DerGol...lum 我不知道为什么,我试过 FastBlur 他们的示例 apk 工作得很好,但是当我实施它们时,我会模糊整个图像:( 是的。只需将模糊应用于background
图像。不是src
。 android:src
在“第一平面”图像上工作。 android:background
仅在后台工作。有 Java 等价物:setDrawable()
和 setBackgroundDrawable()
- 分别是,因为你必须在你的代码中做到这一点。不过,您可能必须禁用硬件加速。
if (sdk
只需用底部视图的高度剪切图像的底部,然后模糊该位图
【参考方案1】:
将这两个类添加到您的应用中,
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<View> 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 文件中:
<FrameLayout
android:id="@+id/fl_uploadedView"
android:layout_
android:layout_
android:layout_margin="@dimen/_10sdp">
<ImageView
android:id="@+id/dv_uploadedPic"
android:layout_
android:layout_
android:contentDescription="@string/app_name"
android:scaleType="centerCrop"
android:src="@color/gray" />
<BlurLayout
android:id="@+id/ll_blurView"
android:layout_
android:layout_
android:layout_gravity="bottom">
<TextView
android:id="@+id/tv_fileName"
android:layout_
android:layout_
android:layout_gravity="left"
android:padding="@dimen/_5sdp"
android:textSize="@dimen/_10sdp"
/>
</BlurLayout>
</FrameLayout>
不要忘记将其添加到 值 > attr.xml
<!--
Blur Layout start
-->
<declare-styleable name="BlurLayout">
<attr name="downscaleFactor" format="float" />
<attr name="blurRadius" format="integer" />
<attr name="fps" format="integer" />
</declare-styleable>
<!--
Blur Layout end
-->
【讨论】:
如果不是不断地创建模糊位图、无效化、重绘、重新创建......这对应用程序性能非常不利。【参考方案2】:这可以通过以下步骤实现:
通过裁剪背景图像提取LinearLayout的背景图像。 现在扩展 LinearLayout 类。
覆盖 OnDraw(Canvas mCanvas) 方法。
在您的自定义 LinearLayout 类中创建两个方法:
-
绘制位图
绘制颜色。
首先调用 DrawBitmap 函数,方法是将您从 ViewPager 获得的偏移量赋予背景图像,以便在用户滑动屏幕时图像移动。
最后用你的透明度绘制颜色
希望这能解决你的问题。
此示例代码
How to Blur a View
【讨论】:
【参考方案3】:试试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();
【讨论】:
【参考方案4】:以下代码将使用以下代码模糊图像的左右两侧:
ViewPictureActivity 内部:
private void applyBlur(final ImageView image)
image.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
@Override
public boolean onPreDraw()
image.getViewTreeObserver().removeOnPreDrawListener(this);
image.buildDrawingCache();
Bitmap bmp = image.getDrawingCache();
blur(bmp, image);
return true;
);
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private void blur(Bitmap bkg, View view)
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, 100, 0,null);
canvas.drawBitmap(bkg, -95,0,null);
RenderScript rs = RenderScript.create(getApplicationContext());
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();
//end blur
将此类添加到您的项目中:
public class ZoomableImageView extends android.support.v7.widget.AppCompatImageView
Matrix matrix = new Matrix();
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
static final int CLICK = 3;
int mode = NONE;
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 4f;
float[] m;
float redundantXSpace, redundantYSpace;
float width, height;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;
ScaleGestureDetector mScaleDetector;
Context context;
public ZoomableImageView(Context context, AttributeSet attr)
super(context, attr);
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
mScaleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction())
//when one finger is touching
//set the mode to DRAG
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
//when two fingers are touching
//set the mode to ZOOM
case MotionEvent.ACTION_POINTER_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = ZOOM;
break;
//when a finger moves
//If mode is applicable move image
case MotionEvent.ACTION_MOVE:
//if the mode is ZOOM or
//if the mode is DRAG and already zoomed
if (mode == ZOOM || (mode == DRAG && saveScale > minScale))
float deltaX = curr.x - last.x;// x difference
float deltaY = curr.y - last.y;// y difference
float scaleWidth = Math.round(origWidth * saveScale);// width after applying current scale
float scaleHeight = Math.round(origHeight * saveScale);// height after applying current scale
//if scaleWidth is smaller than the views width
//in other words if the image width fits in the view
//limit left and right movement
if (scaleWidth < width)
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
//if scaleHeight is smaller than the views height
//in other words if the image height fits in the view
//limit up and down movement
else if (scaleHeight < height)
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
//if the image doesnt fit in the width or height
//limit both up and down and left and right
else
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
//move the image with the matrix
matrix.postTranslate(deltaX, deltaY);
//set the last touch location to the current
last.set(curr.x, curr.y);
break;
//first finger is lifted
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
// second finger is lifted
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
setImageMatrix(matrix);
invalidate();
return true;
);
@Override
public void setImageBitmap(Bitmap bm)
super.setImageBitmap(bm);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
public void setMaxZoom(float x)
maxScale = x;
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
@Override
public boolean onScaleBegin(ScaleGestureDetector detector)
mode = ZOOM;
return true;
@Override
public boolean onScale(ScaleGestureDetector detector)
float mScaleFactor = detector.getScaleFactor();
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale)
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
else if (saveScale < minScale)
saveScale = minScale;
mScaleFactor = minScale / origScale;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
if (origWidth * saveScale <= width || origHeight * saveScale <= height)
matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1)
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1)
if (Math.round(origWidth * saveScale) < width)
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
else
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
else
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1)
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
return true;
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
//Fit to screen.
float scale;
float scaleX = width / bmWidth;
float scaleY = height / bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;
// Center the image
redundantYSpace = height - (scale * bmHeight) ;
redundantXSpace = width - (scale * bmWidth);
redundantYSpace /= 2;
redundantXSpace /= 2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
我使用以下布局来显示图像:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context="com.example.yourpackagename">
<com.example.yourpackagename.ZoomableImageView
android:id="@+id/zivImage"
android:layout_
android:layout_ />
使用 ViewPictureActivity 中的代码:
ZoomableImageView zifImage = findViewById(R.id.zivImage);
zifImage.setImageBitmap(HelperClass.clientImageBitmap);
applyBlur(zifImage);
此答案中使用的代码取自上述答案并进行了修改。
希望这会有所帮助。
【讨论】:
【参考方案5】:使用GitHub: wasabeef's Blurry。它的更新日期为 2021 年,适用于 API >= 21。
Blurry.with(context)
.capture(viewToBlur)
.into(imageViewWithTheBlurredImage)
或者这个以位图为源
Blurry.with(context).from(bitmap).into(imageView)
此外,如果有一个来来去去的键盘,并且我们复制的屏幕布局在键盘上方,我们可以使用此 Kotlin 代码更新模糊视图(并在 imageViewWithTheBlurredImage
上使用 layout_height=wrap_content)。
private fun registerBlurryListenerForFutureLayoutChanges()
rootViewContainerToBlur.doOnNextLayout
if (!isDestroyed) rootViewContainerToBlur.doOnPreDraw
if (!isDestroyed)
captureAndBlur()
registerBlurryListenerForFutureLayoutChanges()
【讨论】:
【参考方案6】:Dmitry Saviuk 的这个库做得很好。配置和使用说明一目了然:
BlurView on GitHub
【讨论】:
这个 500px 已经很老了,它依赖的 RenderScript 现在显然已经消失了,developer.android.com/guide/topics/renderscript/migrate,该库没有构建,maven 库也消失了。 @arberg 感谢您的评论。是的,您是对的-我最初在答案中提到的 500px 库已经很旧并且没有维护。我已经搬到另一个图书馆(来自 Dmitry Saviuk),我现在正在更新答案。另外,在框架提供对创建模糊的原生支持之前,您是否会说这些渲染脚本库是用于创建模糊效果的后备(并且唯一?)选项? 我对渲染脚本一无所知,我只是看到它很久以前就被弃用了。我也确实找到了这份工作的包,并在这里创建了一个答案:***.com/a/69417068/197141 我确实遇到了 Blurry 库,但是答案中提到的库确实更好地解决了这个问题中提出的问题.. 那是 - 模糊特定视图背后的背景.. 而不是视图本身。就这个问题而言,这是关键点。以上是关于Android Blur View(模糊视图背后的背景)的主要内容,如果未能解决你的问题,请参考以下文章
移动端UI设计越来越流行的高斯模糊(Gaussian blur)和毛玻璃效果(磨砂效果),如何使用Android RenderScript简单实现?