0.需要的效果
<-圖一 <-圖二
1.實現
先寫一個dialog
import android.app.Dialog;
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.RotateAnimation;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.newcircle.R;
/**
* Author: yubin
* Time:2018/8/1 11:50
* Tips: 高斯模糊背景對話框
*/
public class CircleVagueDialog extends Dialog {
private AdapterView.OnItemClickListener mItemClickListener;
public CircleVagueDialog setOnItemClickListener(AdapterView.OnItemClickListener itemClickListener) {
mItemClickListener = itemClickListener;
return this;
}
public CircleVagueDialog setOnDismiss(OnDismissListener dismissListener) {
setOnDismissListener(dismissListener);
return this;
}
/**
* @param context
* @param blurredView 模糊之前的View 一般頁面的根佈局
* @param vagueHeight 距離底部的高度 -1時全屏模糊
* @param res 彈出的佈局
*/
public CircleVagueDialog(@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);
BlurringView mBlurringView = view.findViewById(R.id.blurring_view);
// View blurredView = view.findViewById(R.id.blurring_view);
//給出了模糊視圖並刷新模糊視圖。
mBlurringView.setBlurredView(blurredView, vagueHeight);
mBlurringView.invalidate();
view.measure(0, 0);
if (vagueHeight != -1) {
lp.height = view.getMeasuredHeight();
}
dialogWindow.setAttributes(lp);
dialogWindow.setWindowAnimations(R.style.popupwindow); //添加動畫
LinearLayout ll_release = view.findViewById(R.id.ll_release);
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();
});
}
ImageView ivClose = view.findViewById(R.id.iv_close);
ivClose.setAnimation(new RotateAnimation(270, 0, ivClose.getWidth() / 2, ivClose.getHeight() / 2));
ivClose.setOnClickListener(view1 -> dismiss());
setContentView(view);
} catch (Exception e) {
e.printStackTrace();
}
}
}
需要的BlurringView
import android.content.Context;
import android.content.res.Resources;
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.view.View;
import com.newcircle.R;
import com.smartcity.common.commonprovider.utils.DensityUtils;
/**
* 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);
final Resources res = getResources();
final int defaultBlurRadius = 11;
final int defaultDownsampleFactor = 6;
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(DensityUtils.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 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中加三個自定義屬性
<declare-styleable name="PxBlurringView">
<attr name="blurRadius" format="integer"/>
<attr name="downsampleFactor" format="integer"/>
<attr name="overlayColor" format="color"/>
</declare-styleable>
2.使用
佈局示例
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff">
<com.newcircle.widget.BlurringView
android:id="@+id/blurring_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
app:blurRadius="25"
app:downsampleFactor="1"
app:overlayColor="#B3FFFFFF" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/y397"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:id="@+id/ll_release"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/iv_close"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_release_circle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/qz_fabu_quanzi"
android:foreground="?android:attr/selectableItemBackground"
android:gravity="center"
android:text="建圈子" />
<TextView
android:id="@+id/tv_release_dynamic"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/newcircle_release_dynamic"
android:foreground="?android:attr/selectableItemBackground"
android:gravity="center"
android:text="發動態" />
<TextView
android:id="@+id/tv_release_active"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="@drawable/newcircle_release_active"
android:foreground="?android:attr/selectableItemBackground"
android:gravity="center"
android:onClick="circleMember"
android:text="發活動" />
</LinearLayout>
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:padding="@dimen/x60"
android:src="@drawable/newcircle_close" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
圖一效果
new CircleVagueDialog(mContext, findViewById(R.id.root), -1, 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 CircleVagueDialog(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();