参考链接
https://www.jianshu.com/p/97b3bd15f076
效果图
自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BlurringView">
<attr name="blurRadius" format="integer"/>
<attr name="downSampleFactor" format="integer"/>
<attr name="overlayColor" format="color"/>
</declare-styleable>
</resources>
自定义view
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);
//模糊半径 值越大,性能要求越高,模糊半径不能超过25
final int defaultBlurRadius = 12;
//采集样式
final int defaultDownSampleFactor = 2;
//覆盖颜色
final int defaultOverlayColor = Color.GRAY;
//初始化RenderScript
initializeRenderScript(context);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BlurringView);
setBlurRadius(a.getInt(R.styleable.BlurringView_blurRadius, defaultBlurRadius));
setDownSampleFactor(a.getInt(R.styleable.BlurringView_downSampleFactor,
defaultDownSampleFactor));
setOverlayColor(a.getColor(R.styleable.BlurringView_overlayColor, defaultOverlayColor));
a.recycle();
}
public void setBlurredView(View blurredView) {
mBlurredView = blurredView;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mBlurredView != null) {
if (prepare()) {
// If the background of the blurred view is a color drawable, we use it to clear
// the blurring canvas, which ensures that edges of the child views are blurred
// as well; otherwise we clear the blurring canvas with a transparent color.
if (mBlurredView.getBackground() != null && mBlurredView.getBackground() instanceof ColorDrawable) {
mBitmapToBlur.eraseColor(((ColorDrawable) mBlurredView.getBackground()).getColor());
} else {
mBitmapToBlur.eraseColor(Color.TRANSPARENT);
}
//将需要被模糊的布局画成bitmap
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;
// The following manipulation is to avoid some RenderScript artifacts at the edge.
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();
}
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/abc"
android:text="xxx"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ccc"
android:gravity="center"
android:textSize="50sp" />
<com.example.myratingbar.BlurringView
android:id="@+id/blurring"
app:blurRadius="5"
app:downSampleFactor="5"
app:overlayColor="#50000000"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
mainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BlurringView view = findViewById(R.id.blurring);//高斯模糊层
View text = findViewById(R.id.abc);//被模糊层
view.setBlurredView(text);
}
}