项目中需要运用到毛玻璃的效果。经过搜索查阅,踩了一些坑,找到了一条暂时可行的办法。
其中,核心的控件是使用RenderScript这个类,这个类属于jni类,在较低版本的Android系统中,是不具备它的相关方法的。所以我们只能使用support.v8里面的类。然而,support.v8并没有默认地放在新建工程中,因此我们需要自己去添加。
第一步:将D:\AndroidSdk\build-tools\23.0.1\renderscript\lib\packaged 目录下的armeabi-v7a和x86文件夹置于工程的libs路径中
第二步:在build.gradle中写脚本编译这两个.so文件
task nativeLibsToJar(type: Zip, description: "create a jar archive of the native libs") { destinationDir file("$projectDir/libs") baseName "Native_Libs2" extension "jar" from fileTree(dir: "libs", include: "**/*.so") into "lib" } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn(nativeLibsToJar) }
第三步:Rebuild Project
第四步:添加刚刚编译的jar包Native_Libs2
第五步:毛玻璃效果的方法
private void blur(Bitmap overlay, View view, int radius) { RenderScript rs = RenderScript.create(this); 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(); }
PS:这个方法中radius为图片模糊的粒度。我们进入setRadius方法中,可以看到
public void setRadius(float radius) { if(radius > 0.0F && radius <= 25.0F) { this.setVar(0, radius); } else { throw new RSIllegalArgumentException("Radius out of range (0 < r <= 25)."); } }
radius最大只能是25.0
我猜想,在设计这个方法时,开发人员也考虑到这个方法是一个时间复杂度比较高的方法,尤其在大图片,需要较大模糊程度的情况下,会有很大的概率出现性能问题,甚至OOM。
那么,如果我们需要比25更模糊的情况,或是,有一张较大的图片需要模糊化时,该怎么办呢?
常用的方法,即是,将原来需要模糊化的图片先缩小,再模糊化,最后再显示。经过一轮缩小之后,系统会自动将一些象素点综合成一个,经过模糊再放大,获得的模糊程度将高于直接模糊化的程度。
Done!