Android 模糊视图(视图背后的模糊背景) [英] Android Blur View (Blur background behind the view)

查看:128
本文介绍了Android 模糊视图(视图背后的模糊背景)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使图像的底部像图像一样模糊顶部的视图.

我尝试使用 Rendenscript 模糊它,但我无法仅模糊视图后面的部分.:(

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

另外,一个重要的部分是我在 ViewPager 中使用它,因此需要像

解决方案

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

1> BlurKit.Java

公共类 BlurKit {私有静态 BlurKit 实例;私有 RenderScript rs;公共静态无效初始化(上下文上下文){如果(实例!= null){返回;}实例 = 新的 BlurKit();instance.rs = RenderScript.create(context);}公共位图模糊(位图源,整数半径){最终分配输入 = Allocation.createFromBitmap(rs, src);最终分配输出 = Allocation.createTyped(rs, input.getType());最终的 ScriptIntrinsicBlur 脚本;如果 (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {脚本 = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));脚本.setRadius(半径);脚本.setInput(输入);脚本.forEach(输出);}output.copyTo(src);返回源代码;}公共位图模糊(查看源代码,整数半径){位图 bitmap = getBitmapForView(src, 1f);返回模糊(位图,半径);}公共位图 fastBlur(查看 src,int 半径,浮动 downscaleFactor){位图 bitmap = getBitmapForView(src, downscaleFactor);返回模糊(位图,半径);}私有位图 getBitmapForView(View src, float downscaleFactor) {位图位图 = Bitmap.createBitmap((int) (src.getWidth() * downscaleFactor),(int) (src.getHeight() * downscaleFactor),位图.Config.ARGB_4444);Canvas canvas = new Canvas(位图);矩阵矩阵 = 新矩阵();matrix.preScale(downscaleFactor, downscaleFactor);canvas.setMatrix(矩阵);src.draw(画布);返回位图;}公共静态 BlurKit getInstance() {如果(实例 == 空){throw new RuntimeException("BlurKit 未初始化!");}返回实例;}}

2> BlurLayout.Java

public class BlurLayout extends FrameLayout {公共静态最终浮动 DEFAULT_DOWNSCALE_FACTOR = 0.12f;public static final int DEFAULT_BLUR_RADIUS = 12;public static final int DEFAULT_FPS = 60;//自定义属性/** 在模糊之前缩放视图位图的因子.*/私人浮动 mDownscaleFactor;/** 模糊半径直接传递给 stackblur 库.*/私有 int mBlurRadius;/** 每秒要做的模糊失效次数.*/私人 int mFPS;//计算出的类依赖/** 引用顶级父级的视图.如需检索,请参阅 {@link #getActivityView() getActivityView}.*/私有弱引用活动视图;公共模糊布局(上下文上下文){超级(上下文,空);}公共模糊布局(上下文上下文,属性集属性){超级(上下文,属性);BlurKit.init(上下文);TypedArray a = context.getTheme().obtainStyledAttributes(属性,R.styleable.BlurLayout,0, 0);尝试 {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);} 最后 {a.recycle();}如果 (mFPS > 0) {Choreographer.getInstance().postFrameCallback(invalidationLoop);}}/** Choreographer 回调,重新绘制模糊并安排另一个回调.*/private Choreographer.FrameCallback invalidationLoop = new Choreographer.FrameCallback() {@覆盖public void doFrame(long frameTimeNanos) {无效();Choreographer.getInstance().postFrameCallbackDelayed(this, 1000/mFPS);}};/*** {@inheritDoc}*/@覆盖公共无效无效(){super.invalidate();位图 bitmap = blur();如果(位图!= null){setBackground(new BitmapDrawable(bitmap));}}/*** 为内容重新创建模糊并将其设置为背景.*/私人位图模糊(){如果 (getContext() == null) {返回空;}//检查对父视图的引用.//如果不可用,尝试制作它.if (mActivityView == null || mActivityView.get() == null) {mActivityView = new WeakReference<>(getActivityView());如果 (mActivityView.get() == null) {返回空;}}//计算与父视图的相对点.点 pointRelativeToActivityView = getPositionInScreen();//在创建父视图位图之前将 alpha 设置为 0.//模糊视图在创建的位图中不应该可见.setAlpha(0);//边界检查的屏幕尺寸int screenWidth = mActivityView.get().getWidth();int screenHeight = mActivityView.get().getHeight();//模糊位图的最终尺寸.int width = (int) (getWidth() * mDownscaleFactor);int height = (int) (getHeight() * mDownscaleFactor);//裁剪位图的 X/Y 位置.int x = (int) (pointRelativeToActivityView.x * mDownscaleFactor);int y = (int) (pointRelativeToActivityView.y * mDownscaleFactor);//填充以添加到裁剪预模糊.//直接模糊到边缘会产生副作用,因此添加了填充.int xPadding = getWidth()/8;int yPadding = getHeight()/8;//为每一边独立计算填充,检查边缘.int leftOffset = -xPadding;leftOffset = x + leftOffset >= 0 ?左偏移量:0;int rightOffset = xPadding;rightOffset = x + getWidth() + rightOffset <= screenWidth ?rightOffset : screenWidth - getWidth() - x;int topOffset = -yPadding;topOffset = y + topOffset >= 0 ?顶部偏移量:0;int bottomOffset = yPadding;底部偏移 = y + 高度 + 底部偏移 <= 屏幕高度 ?底部偏移量:0;//创建父视图位图,裁剪到带有上方填充的 BlurLayout 区域.位图位图;尝试 {位图 = getDownscaledBitmapForView(mActivityView.get(),新矩形(pointRelativeToActivityView.x + leftOffset,pointRelativeToActivityView.y + topOffset,pointRelativeToActivityView.x + getWidth() + Math.abs(leftOffset) + rightOffset,pointRelativeToActivityView.y + getHeight() + Math.abs(topOffset) + bottomOffset),mDownscaleFactor);} catch (NullPointerException e) {返回空;}//模糊位图.位图 = BlurKit.getInstance().blur(bitmap, mBlurRadius);//再次裁剪位图以去除填充.位图 = Bitmap.createBitmap(位图,(int) (Math.abs(leftOffset) * mDownscaleFactor),(int) (Math.abs(topOffset) * mDownscaleFactor),宽度,高度);//使自己再次可见.setAlpha(1);//将背景设置为模糊位图.返回位图;}/*** 将上下文转换为 Activity 并尝试使用窗口装饰视图创建视图引用.* @return 查看整个活动的参考.*/私人视图 getActivityView() {活动活动;尝试 {活动=(活动)getContext();} catch (ClassCastException e) {返回空;}返回activity.getWindow().getDecorView().findViewById(android.R.id.content);}/*** 返回屏幕中的位置.左抽象以允许特定的实现,例如* 缓存行为.*/私有点 getPositionInScreen() {返回 getPositionInScreen(this);}/*** 查找父视图的Point,并通过self getX() 和getY() 偏移结果.* @return Point 确定传入视图在其所有 ViewParents 中的位置.*/私人点 getPositionInScreen(查看视图){如果 (getParent() == null) {返回新点();}ViewGroup 父级;尝试 {parent = (ViewGroup) view.getParent();} 捕获(异常 e){返回新点();}如果(父 == 空){返回新点();}点点 = getPositionInScreen(parent);point.offset((int) view.getX(), (int) view.getY());返回点;}/*** 用户使用 View 引用来创建位图,并使用传入的因子将其缩小.* 使用 Rect 将视图裁剪为位图.* @return 位图由视图制作,由 downscaleFactor 缩小.* @throws NullPointerException*/私有位图 getDownscaledBitmapForView(View view, Rect crop, float downscaleFactor) 抛出 NullPointerException {查看 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) {抛出新的 NullPointerException();}浮动 dx = -crop.left * downscaleFactor;float dy = -crop.top * downscaleFactor;位图位图 = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);Canvas canvas = new Canvas(位图);矩阵矩阵 = 新矩阵();matrix.preScale(downscaleFactor, downscaleFactor);矩阵.postTranslate(dx, dy);canvas.setMatrix(矩阵);screenView.draw(画布);返回位图;}/*** 设置缩小因子以使用预模糊.* 见 {@link #mDownscaleFactor}.*/公共无效setDownscaleFactor(浮动downscaleFactor){this.mDownscaleFactor = downscaleFactor;无效();}/*** 设置用于缩小位图的模糊半径.* 见 {@link #mBlurRadius}.*/公共无效 setBlurRadius(int blurRadius) {this.mBlurRadius = 模糊半径;无效();}/*** 设置 FPS 使模糊无效.* 见 {@link #mFPS}.*/公共无效 setFPS(int fps) {this.mFPS = fps;}}

在 XML 文件中:

 <图像视图android:id="@+id/dv_uploadedPic"android:layout_width="match_parent"android:layout_height="@dimen/_150sdp"android:contentDescription="@string/app_name"android:scaleType="centerCrop"android:src="@color/gray"/><模糊布局android:id="@+id/ll_blurView"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="底部"><文本视图android:id="@+id/tv_fileName"android:layout_width="match_parent"android:layout_height="wrap_content"机器人:layout_gravity="左"android:padding="@dimen/_5sdp"android:textSize="@dimen/_10sdp"/></BlurLayout></FrameLayout>

不要忘记将此添加到值> attr.xml