0.需要的效果
1.实现
先写一个dialog
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
/**
* Author: yubin
* Time:2018/8/1 11:50
* Tips: 高斯模糊背景对话框
*/
public class VagueDialog extends Dialog {
private AdapterView.OnItemClickListener mItemClickListener;
public VagueDialog setOnItemClickListener(AdapterView.OnItemClickListener itemClickListener) {
mItemClickListener = itemClickListener;
return this;
}
public VagueDialog setOnDismiss(OnDismissListener dismissListener) {
setOnDismissListener(dismissListener);
return this;
}
/**
* 全屏的模糊弹窗
*
* @param context
* @param res
*/
public VagueDialog(@NonNull Activity context, @LayoutRes int res) {
this(context, context.getWindow().getDecorView(), -1, res);
}
/**
* @param context
* @param blurredView 模糊之前的View
* @param vagueHeight 距离底部的高度 -1时全屏模糊
* @param res 弹出的布局 需包含id blurring_view rl_button rl_button ll_release iv_close
*/
public VagueDialog(@NonNull Context context, View blurredView, int vagueHeight, @LayoutRes int res) {
super(context, R.style.circle_vague_dialog_style);
//获取当前Activity所在的窗体
try {
Window dialogWindow = getWindow();
//设置Dialog从窗体底部弹出
dialogWindow.setGravity(Gravity.BOTTOM);
dialogWindow.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
View view = View.inflate(context, res, null);
//获取View 的id
int bv = context.getResources().getIdentifier("blurring_view", "id", context.getPackageName());
BlurringView mBlurringView = view.findViewById(bv);
//给出了模糊视图并刷新模糊视图。
if (blurredView != null) {
mBlurringView.setBlurredView(blurredView, vagueHeight);
mBlurringView.invalidate();
}
view.measure(0, 0);
if (vagueHeight != -1) {
lp.height = view.getMeasuredHeight();
}
dialogWindow.setAttributes(lp);
if (vagueHeight == -1) {
//获取View 的id
int rl = context.getResources().getIdentifier("rl_button", "id", context.getPackageName());
RelativeLayout rl_button = view.findViewById(rl);
rl_button.setAnimation(AnimationUtils.loadAnimation(context, R.anim.pop_enter_anim));
} else
dialogWindow.setWindowAnimations(R.style.popupwindow); //添加动画
//获取View 的id
int ll = context.getResources().getIdentifier("ll_release", "id", context.getPackageName());
LinearLayout ll_release = view.findViewById(ll);
for (int i = 0; i < ll_release.getChildCount(); i++) {
final int finalI = i;
View childAt = ll_release.getChildAt(i);
childAt.setOnClickListener(view1 -> {
mItemClickListener.onItemClick(null, childAt, finalI, finalI);
dismiss();
});
}
//获取View 的id
int iv_close = context.getResources().getIdentifier("iv_close", "id", context.getPackageName());
ImageView ivClose = view.findViewById(iv_close);
ivClose.setOnClickListener(view1 -> dismiss());
setContentView(view);
} catch (Exception e) {
e.printStackTrace();
}
}
}
需要的BlurringView
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
/**
* Created by yubin
* 2018/8/1 0007-下午 3:27
*/
public class BlurringView extends View {
public BlurringView(Context context) {
this(context, null);
}
public BlurringView(Context context, AttributeSet attrs) {
super(context, attrs);
//0 < radius <= 25
final int defaultBlurRadius = 11;
// defaultDownsampleFactor > 0
final int defaultDownsampleFactor = 6;
//模糊的颜色 默认50%白色
final int defaultOverlayColor = Color.parseColor("#50FFFFFF");
initializeRenderScript(context);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PxBlurringView);
setBlurRadius(a.getInt(R.styleable.PxBlurringView_blurRadius, defaultBlurRadius));
setDownsampleFactor(a.getInt(R.styleable.PxBlurringView_downsampleFactor,
defaultDownsampleFactor));
setOverlayColor(a.getColor(R.styleable.PxBlurringView_overlayColor, defaultOverlayColor));
a.recycle();
}
private int mVagueHeight;
/**
* @param blurredView 屏幕跟布局
* @param vagueHeight 距离底部的高度 dp -1 全屏
*/
public void setBlurredView(View blurredView, int vagueHeight) {
mBlurredView = blurredView;
mVagueHeight = vagueHeight;
}
@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);
}
mBlurredView.draw(mBlurringCanvas);
if (mVagueHeight != -1) {
blur(dp2px(this.getContext(), mVagueHeight));
} else
blur(mVagueHeight);
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 static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(1, dpVal, context.getResources().getDisplayMetrics());
}
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;
}
/**
* 按长方形裁切图片
*
* @param bitmap
* @param imgHeight 剪裁后的高度
* @return
*/
private Bitmap imageCropWithRect(Bitmap bitmap, int imgHeight) {
if (bitmap == null) {
return null;
}
int w = bitmap.getWidth(); // 得到图片的宽,高
int h = bitmap.getHeight();
/*int nw, nh, retX, retY;
if (w > h) {
nw = h / 2;
nh = h;
retX = (w - nw) / 2;
retY = 0;
} else {
nw = w / 2;
nh = w;
retX = w / 4;
retY = (h - w) / 2;
}*/
// 下面这句是关键
Bitmap bmp = Bitmap.createBitmap(bitmap, 0, h - imgHeight, w, imgHeight, null, false);
if (bitmap != null && !bitmap.equals(bmp) && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
return bmp;// Bitmap.createBitmap(bitmap, retX, retY, nw, nh, null,
// false);
}
/**
* android.renderscript.RSIllegalArgumentException: Cannot update allocation from bitmap, sizes mismatch
*
* @param h
*/
protected void blur(int h) {
try {
mBlurInput.copyFrom(mBitmapToBlur);
mBlurScript.setInput(mBlurInput);
mBlurScript.forEach(mBlurOutput);
mBlurOutput.copyTo(mBlurredBitmap);
if (h != -1) {
mBlurredBitmap = imageCropWithRect(mBlurredBitmap, h);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mRenderScript != null) {
mRenderScript.destroy();
}
}
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;
}
style中加三个自定义属性
anim 文件夹中
pop_enter_anim.xml
pop_exit_anim.xml
2.使用
布局示例
图一效果
new VagueDialog(mContext, R.layout.dialog_home_publish)
.setOnDismiss(dialogInterface -> //do something)
.setOnItemClickListener((adapterView, view1, i, l) -> {
switch (i) {
case 0:
AAAActivity.start(mContext);
break;
case 1:
BBBActivity.start(mContext);
break;
case 2:
CCCActivity.start(mContext);
break;
}
}).show();
图二效果
new VagueDialog(mContext, root, 398/2, R.layout.dialog_release)
.setOnItemClickListener((adapterView, view1, i, l) -> {
switch (i) {
case 0:
AAAActivity.start(mContext);
break;
case 1:
BBBtActivity.start(mContext);
break;
}
}).show();