diff --git a/README.md b/README.md index 89a9367..2a99385 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ Android各种小功能小UI的开源和测试 都可以写到这个上面 想要 2. activity表示这是一个窗口 例如 aa_activity.xml aa_aa_activity.xml 3. fragment表示这是一个碎片 例如 aa_fragment.xml aa_aa_fragment.xml 4. view表示这是一个自定义控件 例如 aa_view.xml aa_aa_view.xml +## 导入的第三放库(防止用户加入重复的库) +1. glide = "4.16.0" 谢谢你们能持续为这个项目做出贡献 \ No newline at end of file diff --git a/blurview/.gitignore b/blurview/.gitignore deleted file mode 100644 index 42afabf..0000000 --- a/blurview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/blurview/build.gradle b/blurview/build.gradle deleted file mode 100644 index 3d13aed..0000000 --- a/blurview/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -plugins { - id 'com.android.library' -} - -android { - compileSdk 31 - namespace "net.center.blurview" - - defaultConfig { - minSdk 19 - targetSdk 31 - - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } -} - -dependencies { - compileOnly 'androidx.appcompat:appcompat:1.4.1' -} \ No newline at end of file diff --git a/blurview/src/main/AndroidManifest.xml b/blurview/src/main/AndroidManifest.xml deleted file mode 100644 index d1ce83e..0000000 --- a/blurview/src/main/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/blurview/src/main/java/net/center/blurview/ShapeBlurView.java b/blurview/src/main/java/net/center/blurview/ShapeBlurView.java deleted file mode 100644 index 2516f19..0000000 --- a/blurview/src/main/java/net/center/blurview/ShapeBlurView.java +++ /dev/null @@ -1,977 +0,0 @@ -package net.center.blurview; - -import android.app.Activity; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.BitmapShader; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Shader; -import android.os.Build; -import android.util.AttributeSet; -import android.util.StateSet; -import android.util.TypedValue; -import android.view.View; -import android.view.ViewTreeObserver; - -import net.center.blurview.enu.BlurCorner; -import net.center.blurview.enu.BlurMode; -import net.center.blurview.impl.AndroidStockBlurImpl; -import net.center.blurview.impl.AndroidXBlurImpl; -import net.center.blurview.impl.BlurImpl; -import net.center.blurview.impl.EmptyBlurImpl; -import net.center.blurview.impl.SupportLibraryBlurImpl; - -import androidx.annotation.ColorInt; -import androidx.annotation.ColorRes; -import androidx.annotation.DimenRes; -import androidx.annotation.FloatRange; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; - -/** - * A realtime blurring overlay (like iOS UIVisualEffectView). Just put it above - * the view you want to blur and it doesn't have to be in the same ViewGroup - */ -public class ShapeBlurView extends View { - private Context mContext; - - /** - * default 4 - */ - private float mDownSampleFactor; - /** - * default #000000 - */ - private int mOverlayColor; - /** - * default 10dp (0 < r <= 25) - */ - private float mBlurRadius; - public static final int DEFAULT_BORDER_COLOR = Color.WHITE; - - private final BlurImpl mBlurImpl; - private boolean mDirty; - private Bitmap mBitmapToBlur, mBlurredBitmap; - private Canvas mBlurringCanvas; - private boolean mIsRendering; - - - private final Rect mRectSrc = new Rect(); - private final RectF mRectFDst = new RectF(); - /** - * mDecorView should be the root view of the activity (even if you are on a different window like a dialog) - */ - private View mDecorView; - /** - * If the view is on different root view (usually means we are on a PopupWindow), - * we need to manually call invalidate() in onPreDraw(), otherwise we will not be able to see the changes - */ - private boolean mDifferentRoot; - private static int RENDERING_COUNT; - private static int BLUR_IMPL; - - private int blurMode = BlurMode.MODE_RECTANGLE; - private final Paint mBitmapPaint; - //圆形 相关 - private float cx = 0, cy = 0, cRadius = 0; - - //圆角相关 - private static final float DEFAULT_RADIUS = 0f; - private final float[] mCornerRadii = new float[]{DEFAULT_RADIUS, DEFAULT_RADIUS, DEFAULT_RADIUS, DEFAULT_RADIUS}; - private final Path cornerPath = new Path(); - private float[] cornerRids; - - //边框相关 - private static final float DEFAULT_BORDER_WIDTH = 0f; - - private final RectF mBorderRect = new RectF(); - private final Paint mBorderPaint; - private float mBorderWidth = 0; - private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR); - private Matrix matrix = new Matrix(); - private BitmapShader shader; - - public ShapeBlurView(Context context, AttributeSet attrs) { - super(context, attrs); - mContext = context; - // provide your own by override getBlurImpl() - mBlurImpl = getBlurImpl(); - try { - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShapeBlurView); - mBlurRadius = a.getDimension(R.styleable.ShapeBlurView_blur_radius, - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, context.getResources().getDisplayMetrics())); - mDownSampleFactor = a.getFloat(R.styleable.ShapeBlurView_blur_down_sample, 4); - mOverlayColor = a.getColor(R.styleable.ShapeBlurView_blur_overlay_color, 0x000000); - - float cornerRadiusOverride = - a.getDimensionPixelSize(R.styleable.ShapeBlurView_blur_corner_radius, -1); - mCornerRadii[BlurCorner.TOP_LEFT] = - a.getDimensionPixelSize(R.styleable.ShapeBlurView_blur_corner_radius_top_left, -1); - mCornerRadii[BlurCorner.TOP_RIGHT] = - a.getDimensionPixelSize(R.styleable.ShapeBlurView_blur_corner_radius_top_right, -1); - mCornerRadii[BlurCorner.BOTTOM_RIGHT] = - a.getDimensionPixelSize(R.styleable.ShapeBlurView_blur_corner_radius_bottom_right, -1); - mCornerRadii[BlurCorner.BOTTOM_LEFT] = - a.getDimensionPixelSize(R.styleable.ShapeBlurView_blur_corner_radius_bottom_left, -1); - initCornerData(cornerRadiusOverride); - blurMode = a.getInt(R.styleable.ShapeBlurView_blur_mode, BlurMode.MODE_RECTANGLE); - - mBorderWidth = a.getDimensionPixelSize(R.styleable.ShapeBlurView_blur_border_width, -1); - if (mBorderWidth < 0) { - mBorderWidth = DEFAULT_BORDER_WIDTH; - } - mBorderColor = a.getColorStateList(R.styleable.ShapeBlurView_blur_border_color); - if (mBorderColor == null) { - mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR); - } - - - a.recycle(); - } catch (Exception e) { - e.printStackTrace(); - } - mBitmapPaint = new Paint(); -// mBitmapPaint.setStyle(Paint.Style.FILL); - mBitmapPaint.setAntiAlias(true); - - mBorderPaint = new Paint(); - mBorderPaint.setStyle(Paint.Style.STROKE); - mBorderPaint.setAntiAlias(true); - mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR)); - mBorderPaint.setStrokeWidth(mBorderWidth); - -// matrix = new Matrix(); - } - - private void initCornerData(float cornerRadiusOverride) { - boolean any = false; - for (int i = 0, len = mCornerRadii.length; i < len; i++) { - if (mCornerRadii[i] < 0) { - mCornerRadii[i] = 0f; - } else { - any = true; - } - } - if (!any) { - if (cornerRadiusOverride < 0) { - cornerRadiusOverride = DEFAULT_RADIUS; - } - for (int i = 0, len = mCornerRadii.length; i < len; i++) { - mCornerRadii[i] = cornerRadiusOverride; - } - } - initCornerRids(); - } - - private void initCornerRids() { - if (cornerRids == null) { - cornerRids = new float[]{mCornerRadii[BlurCorner.TOP_LEFT], mCornerRadii[BlurCorner.TOP_LEFT], - mCornerRadii[BlurCorner.TOP_RIGHT], mCornerRadii[BlurCorner.TOP_RIGHT], - mCornerRadii[BlurCorner.BOTTOM_RIGHT], mCornerRadii[BlurCorner.BOTTOM_RIGHT], - mCornerRadii[BlurCorner.BOTTOM_LEFT], mCornerRadii[BlurCorner.BOTTOM_LEFT]}; - } else { - cornerRids[0] = mCornerRadii[BlurCorner.TOP_LEFT]; - cornerRids[1] = mCornerRadii[BlurCorner.TOP_LEFT]; - cornerRids[2] = mCornerRadii[BlurCorner.TOP_RIGHT]; - cornerRids[3] = mCornerRadii[BlurCorner.TOP_RIGHT]; - cornerRids[4] = mCornerRadii[BlurCorner.BOTTOM_RIGHT]; - cornerRids[5] = mCornerRadii[BlurCorner.BOTTOM_RIGHT]; - cornerRids[6] = mCornerRadii[BlurCorner.BOTTOM_LEFT]; - cornerRids[7] = mCornerRadii[BlurCorner.BOTTOM_LEFT]; - } - } - - protected BlurImpl getBlurImpl() { - if (BLUR_IMPL == 0) { - // try to use stock impl first - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - try { - AndroidStockBlurImpl impl = new AndroidStockBlurImpl(); - Bitmap bmp = Bitmap.createBitmap(4, 4, Bitmap.Config.ARGB_8888); - impl.prepare(getContext(), bmp, 4); - impl.release(); - bmp.recycle(); - BLUR_IMPL = 3; - } catch (Throwable e) { - } - } - } - if (BLUR_IMPL == 0) { - try { - getClass().getClassLoader().loadClass("androidx.renderscript.RenderScript"); - // initialize RenderScript to load jni impl - // may throw unsatisfied link error - AndroidXBlurImpl impl = new AndroidXBlurImpl(); - Bitmap bmp = Bitmap.createBitmap(4, 4, Bitmap.Config.ARGB_8888); - impl.prepare(getContext(), bmp, 4); - impl.release(); - bmp.recycle(); - BLUR_IMPL = 1; - } catch (Throwable e) { - // class not found or unsatisfied link - } - } - if (BLUR_IMPL == 0) { - try { - getClass().getClassLoader().loadClass("android.support.v8.renderscript.RenderScript"); - // initialize RenderScript to load jni impl - // may throw unsatisfied link error - SupportLibraryBlurImpl impl = new SupportLibraryBlurImpl(); - Bitmap bmp = Bitmap.createBitmap(4, 4, Bitmap.Config.ARGB_8888); - impl.prepare(getContext(), bmp, 4); - impl.release(); - bmp.recycle(); - BLUR_IMPL = 2; - } catch (Throwable e) { - // class not found or unsatisfied link - } - } - if (BLUR_IMPL == 0) { - // fallback to empty impl, which doesn't have blur effect - BLUR_IMPL = -1; - } - switch (BLUR_IMPL) { - case 1: - return new AndroidXBlurImpl(); - case 2: - return new SupportLibraryBlurImpl(); - case 3: - return new AndroidStockBlurImpl(); - default: - return new EmptyBlurImpl(); - } - } - -// public void setBlurRadius(@FloatRange(from = 0, to = 25) float radius) { -// if (mBlurRadius != radius) { -// mBlurRadius = radius; -// mDirty = true; -// invalidate(); -// } -// } - -// public void setDownSampleFactor(float factor) { -// if (factor <= 0) { -// throw new IllegalArgumentException("DownSample factor must be greater than 0."); -// } -// if (mDownSampleFactor != factor) { -// mDownSampleFactor = factor; -// // may also change blur radius -// mDirty = true; -// releaseBitmap(); -// invalidate(); -// } -// } - -// public void setOverlayColor(int color) { -// if (mOverlayColor != color) { -// mOverlayColor = color; -// invalidate(); -// } -// } - - /** - * Set all the corner radii from a dimension resource id. - * - * @param resId dimension resource id of radii. - */ -// public void setCornerRadiusDimen(@DimenRes int resId) { -// float radius = getResources().getDimension(resId); -// setCornerRadius(radius, radius, radius, radius); -// } - - /** - * Set the corner radius of a specific corner in px. - * - * @param radius - */ -// public void setCornerRadius(float radius) { -// setCornerRadius(radius, radius, radius, radius); -// } - - /** - * Set the corner radius of a specific corner in px. - */ -// public void setCornerRadius(@BlurCorner int corner, float radius) { -// if (mCornerRadii[corner] == radius) { -// return; -// } -// mCornerRadii[corner] = radius; -// initCornerRids(); -// invalidate(); -// } - - /** - * Set the corner radius of a specific corner in px. - */ -// public void setCornerRadius(float topLeft, float topRight, float bottomLeft, float bottomRight) { -// if (mCornerRadii[BlurCorner.TOP_LEFT] == topLeft -// && mCornerRadii[BlurCorner.TOP_RIGHT] == topRight -// && mCornerRadii[BlurCorner.BOTTOM_RIGHT] == bottomRight -// && mCornerRadii[BlurCorner.BOTTOM_LEFT] == bottomLeft) { -// return; -// } -// mCornerRadii[BlurCorner.TOP_LEFT] = topLeft; -// mCornerRadii[BlurCorner.TOP_RIGHT] = topRight; -// mCornerRadii[BlurCorner.BOTTOM_LEFT] = bottomLeft; -// mCornerRadii[BlurCorner.BOTTOM_RIGHT] = bottomRight; -// initCornerRids(); -// invalidate(); -// } - - /** - * @return the largest corner radius. - */ - public float getCornerRadius() { - return getMaxCornerRadius(); - } - - /** - * @return the largest corner radius. - */ - public float getMaxCornerRadius() { - float maxRadius = 0; - for (float r : mCornerRadii) { - maxRadius = Math.max(r, maxRadius); - } - return maxRadius; - } - - - public float getBorderWidth() { - return mBorderWidth; - } - -// public void setBorderWidth(@DimenRes int resId) { -// setBorderWidth(getResources().getDimension(resId)); -// } - -// public void setBorderWidth(float width) { -// if (mBorderWidth == width) { -// return; -// } -// mBorderWidth = width; -// invalidate(); -// } - - @ColorInt - public int getBorderColor() { - return mBorderColor.getDefaultColor(); - } - -// public void setBorderColor(@ColorInt int color) { -// setBorderColor(ColorStateList.valueOf(color)); -// } - -// public void setBorderColor(ColorStateList colors) { -// if (mBorderColor.equals(colors)) { -// return; -// } -// mBorderColor = (colors != null) ? colors : ColorStateList.valueOf(DEFAULT_BORDER_COLOR); -// mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR)); -// if (mBorderWidth > 0) { -// invalidate(); -// } -// } - - @BlurMode - public int getBlurMode() { - return this.blurMode; - } - -// public void setBlurMode(@BlurMode int blurMode) { -// if (this.blurMode == blurMode) { -// return; -// } -// this.blurMode = blurMode; -// invalidate(); -// } - - private void releaseBitmap() { - if (mBitmapToBlur != null) { - mBitmapToBlur.recycle(); - mBitmapToBlur = null; - } - if (mBlurredBitmap != null) { - mBlurredBitmap.recycle(); - mBlurredBitmap = null; - } - if (matrix != null) { - matrix = null; - } - if (shader != null) { - shader = null; - } - mContext = null; - } - - protected void release() { - releaseBitmap(); - mBlurImpl.release(); - } - - protected boolean prepare() { - if (mBlurRadius == 0) { - release(); - return false; - } - float downSampleFactor = mDownSampleFactor; - float radius = mBlurRadius / downSampleFactor; - if (radius > 25) { - downSampleFactor = downSampleFactor * radius / 25; - radius = 25; - } - final int width = getWidth(); - final int height = getHeight(); - int scaledWidth = Math.max(1, (int) (width / downSampleFactor)); - int scaledHeight = Math.max(1, (int) (height / downSampleFactor)); - boolean dirty = mDirty; - if (mBlurringCanvas == null || mBlurredBitmap == null - || mBlurredBitmap.getWidth() != scaledWidth - || mBlurredBitmap.getHeight() != scaledHeight) { - dirty = true; - releaseBitmap(); - boolean r = false; - try { - mBitmapToBlur = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); - if (mBitmapToBlur == null) { - return false; - } - mBlurringCanvas = new Canvas(mBitmapToBlur); - mBlurredBitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); - if (mBlurredBitmap == null) { - return false; - } - r = true; - } catch (OutOfMemoryError e) { - // Bitmap.createBitmap() may cause OOM error - // Simply ignore and fallback - } finally { - if (!r) { - release(); - return false; - } - } - } - if (dirty) { - if (mBlurImpl.prepare(getContext(), mBitmapToBlur, radius)) { - mDirty = false; - } else { - return false; - } - } - return true; - } - - protected void blur(Bitmap bitmapToBlur, Bitmap blurredBitmap) { - shader = new BitmapShader(blurredBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - mBlurImpl.blur(bitmapToBlur, blurredBitmap); - } - - private final ViewTreeObserver.OnPreDrawListener preDrawListener = new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - final int[] locations = new int[2]; - Bitmap oldBmp = mBlurredBitmap; - View decor = mDecorView; - if (decor != null && isShown() && prepare()) { - boolean redrawBitmap = mBlurredBitmap != oldBmp; - oldBmp = null; - decor.getLocationOnScreen(locations); - int x = -locations[0]; - int y = -locations[1]; - getLocationOnScreen(locations); - x += locations[0]; - y += locations[1]; - // just erase transparent - mBitmapToBlur.eraseColor(mOverlayColor & 0xffffff); - int rc = mBlurringCanvas.save(); - mIsRendering = true; - RENDERING_COUNT++; - try { - mBlurringCanvas.scale(1.f * mBitmapToBlur.getWidth() / getWidth(), 1.f * mBitmapToBlur.getHeight() / getHeight()); - mBlurringCanvas.translate(-x, -y); - if (decor.getBackground() != null) { - decor.getBackground().draw(mBlurringCanvas); - } - decor.draw(mBlurringCanvas); - } catch (StopException e) { - } finally { - mIsRendering = false; - RENDERING_COUNT--; - mBlurringCanvas.restoreToCount(rc); - } - blur(mBitmapToBlur, mBlurredBitmap); - if (redrawBitmap || mDifferentRoot) { - invalidate(); - } - } - - return true; - } - }; - - protected View getActivityDecorView() { - Context ctx = getContext(); - for (int i = 0; i < 4 && !(ctx instanceof Activity) && ctx instanceof ContextWrapper; i++) { - ctx = ((ContextWrapper) ctx).getBaseContext(); - } - if (ctx instanceof Activity) { - return ((Activity) ctx).getWindow().getDecorView(); - } else { - return null; - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - mDecorView = getActivityDecorView(); - if (mDecorView != null) { - mDecorView.getViewTreeObserver().addOnPreDrawListener(preDrawListener); - mDifferentRoot = mDecorView.getRootView() != getRootView(); - if (mDifferentRoot) { - mDecorView.postInvalidate(); - } - } else { - mDifferentRoot = false; - } - } - - @Override - protected void onDetachedFromWindow() { - if (mDecorView != null) { - mDecorView.getViewTreeObserver().removeOnPreDrawListener(preDrawListener); - } - release(); - super.onDetachedFromWindow(); - } - - @Override - public void draw(Canvas canvas) { - if (mIsRendering) { - // Quit here, don't draw views above me - throw STOP_EXCEPTION; - } else if (RENDERING_COUNT > 0) { - // Doesn't support blurview overlap on another blurview - } else { - super.draw(canvas); - } - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawBlurredBitmap(canvas, mBlurredBitmap, mOverlayColor); - } - - /** - * Custom draw the blurred bitmap and color to define your own shape - * - * @param canvas - * @param blurBitmap - * @param overlayColor - */ - protected void drawBlurredBitmap(Canvas canvas, Bitmap blurBitmap, int overlayColor) { - if (blurBitmap != null) { - if (blurMode == BlurMode.MODE_CIRCLE) { - drawCircleRectBitmap(canvas, blurBitmap, overlayColor); - } else if (blurMode == BlurMode.MODE_OVAL) { - drawOvalRectBitmap(canvas, blurBitmap, overlayColor); - } else { - drawRoundRectBitmap(canvas, blurBitmap, overlayColor); - } - } - } - - /** - * 默认或者画矩形可带圆角 - * - * @param canvas - * @param blurBitmap - * @param overlayColor - */ - private void drawRoundRectBitmap(Canvas canvas, Bitmap blurBitmap, int overlayColor) { - try { - //圆角的半径,依次为左上角xy半径,右上角,右下角,左下角 - mRectFDst.right = getWidth(); - mRectFDst.bottom = getHeight(); - /*向路径中添加圆角矩形。radii数组定义圆角矩形的四个圆角的x,y半径。radii长度必须为8*/ - //Path.Direction.CW:clockwise ,沿顺时针方向绘制,Path.Direction.CCW:counter-clockwise ,沿逆时针方向绘制 - cornerPath.addRoundRect(mRectFDst, cornerRids, Path.Direction.CW); - cornerPath.close(); - canvas.clipPath(cornerPath); - - mRectSrc.right = blurBitmap.getWidth(); - mRectSrc.bottom = blurBitmap.getHeight(); - canvas.drawBitmap(blurBitmap, mRectSrc, mRectFDst, null); - mBitmapPaint.setColor(overlayColor); - canvas.drawRect(mRectFDst, mBitmapPaint); - if (mBorderWidth > 0) { - //目前没找到合适方式 - mBorderPaint.setStrokeWidth(mBorderWidth * 2); - canvas.drawPath(cornerPath, mBorderPaint); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 画椭圆,如果宽高一样则为圆形 - * - * @param canvas - * @param blurBitmap - * @param overlayColor - */ - private void drawOvalRectBitmap(Canvas canvas, Bitmap blurBitmap, int overlayColor) { - try { - mRectFDst.right = getWidth(); - mRectFDst.bottom = getHeight(); - mBitmapPaint.reset(); - mBitmapPaint.setAntiAlias(true); - if (shader == null) { - shader = new BitmapShader(blurBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - } - if (matrix == null) { - matrix = new Matrix(); - matrix.postScale(mRectFDst.width() / blurBitmap.getWidth(), mRectFDst.height() / blurBitmap.getHeight()); - } - shader.setLocalMatrix(matrix); - mBitmapPaint.setShader(shader); - canvas.drawOval(mRectFDst, mBitmapPaint); - mBitmapPaint.reset(); - mBitmapPaint.setAntiAlias(true); - mBitmapPaint.setColor(overlayColor); - canvas.drawOval(mRectFDst, mBitmapPaint); - if (mBorderWidth > 0) { - mBorderRect.set(mRectFDst); - mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2); - canvas.drawOval(mBorderRect, mBorderPaint); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 画圆形,以宽高最小的为半径 - * - * @param canvas - * @param blurBitmap - * @param overlayColor - */ - private void drawCircleRectBitmap(Canvas canvas, Bitmap blurBitmap, int overlayColor) { - try { - mRectFDst.right = getMeasuredWidth(); - mRectFDst.bottom = getMeasuredHeight(); - mRectSrc.right = blurBitmap.getWidth(); - mRectSrc.bottom = blurBitmap.getHeight(); - mBitmapPaint.reset(); - mBitmapPaint.setAntiAlias(true); - if (shader == null) { - shader = new BitmapShader(blurBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - } - if (matrix == null) { - matrix = new Matrix(); - matrix.postScale(mRectFDst.width() / mRectSrc.width(), mRectFDst.height() / mRectSrc.height()); - } - shader.setLocalMatrix(matrix); - mBitmapPaint.setShader(shader); - //前面Scale,故判断以哪一个来取中心点和半径 - if (mRectFDst.width() >= mRectSrc.width()) { - cx = mRectFDst.width() / 2; - cy = mRectFDst.height() / 2; - //取宽高最小的为半径 - cRadius = Math.min(mRectFDst.width(), mRectFDst.height()) / 2; - mBorderRect.set(mRectFDst); - } else { - cx = mRectSrc.width() / 2f; - cy = mRectSrc.height() / 2f; - cRadius = Math.min(mRectSrc.width(), mRectSrc.height()) / 2f; - mBorderRect.set(mRectSrc); - } - canvas.drawCircle(cx, cy, cRadius, mBitmapPaint); - mBitmapPaint.reset(); - mBitmapPaint.setAntiAlias(true); - mBitmapPaint.setColor(overlayColor); - canvas.drawCircle(cx, cy, cRadius, mBitmapPaint); - //使用宽高相等的椭圆为圆形来画边框 - if (mBorderWidth > 0) { - if (mBorderRect.width() > mBorderRect.height()) { - //原本宽大于高,圆是以中心点为圆心和高的一半为半径,椭圆区域是以初始00为开始,故整体向右移动差值 - float dif = Math.abs(mBorderRect.height() - mBorderRect.width()) / 2; - mBorderRect.left = dif; - mBorderRect.right = Math.min(mBorderRect.width(), mBorderRect.height()) + dif; - mBorderRect.bottom = Math.min(mBorderRect.width(), mBorderRect.height()); - } else if (mBorderRect.width() < mBorderRect.height()) { - //原本高大于宽,圆是以中心点为圆心和宽的一半为半径,椭圆区域是以初始00为开始,故整体向下移动差值 - float dif = Math.abs(mBorderRect.height() - mBorderRect.width()) / 2; - mBorderRect.top = dif; - mBorderRect.right = Math.min(mBorderRect.width(), mBorderRect.height()); - mBorderRect.bottom = Math.min(mBorderRect.width(), mBorderRect.height()) + dif; - } else { - //如果快高相同,则不需要偏移,椭圆画出来就是圆 - mBorderRect.right = Math.min(mBorderRect.width(), mBorderRect.height()); - mBorderRect.bottom = Math.min(mBorderRect.width(), mBorderRect.height()); - } - mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2); - canvas.drawOval(mBorderRect, mBorderPaint); - } - } catch (Exception e) { - e.printStackTrace(); - } - - } - - - /** - * dp转px - * - * @param dpValue dp值 - * @return px值 - */ - public int dp2px(final float dpValue) { - final float scale = mContext.getResources().getDisplayMetrics().density; - return (int) (dpValue * scale + 0.5f); - } - - public @NonNull - int[] getState() { - return StateSet.WILD_CARD; - } - - private static class StopException extends RuntimeException { - } - - private static StopException STOP_EXCEPTION = new StopException(); - - /** - * 传入构造器,避免传统的设置一个参数调用一次invalidate()重新绘制 - * - * @return - */ - public void refreshView(Builder builder) { - boolean isInvalidate = false; - if (builder == null) { - return; - } - if (builder.blurMode != -1 && this.blurMode != builder.blurMode) { - this.blurMode = builder.blurMode; - isInvalidate = true; - } - if (builder.mBorderColor != null && !mBorderColor.equals(builder.mBorderColor)) { - this.mBorderColor = builder.mBorderColor; - mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR)); - if (mBorderWidth > 0) { - isInvalidate = true; - } - } - if (builder.mBorderWidth > 0) { - mBorderWidth = builder.mBorderWidth; - mBorderPaint.setStrokeWidth(mBorderWidth); - isInvalidate = true; - } - if (mCornerRadii[BlurCorner.TOP_LEFT] != builder.mCornerRadii[BlurCorner.TOP_LEFT] - || mCornerRadii[BlurCorner.TOP_RIGHT] != builder.mCornerRadii[BlurCorner.TOP_RIGHT] - || mCornerRadii[BlurCorner.BOTTOM_RIGHT] != builder.mCornerRadii[BlurCorner.BOTTOM_RIGHT] - || mCornerRadii[BlurCorner.BOTTOM_LEFT] != builder.mCornerRadii[BlurCorner.BOTTOM_LEFT]) { - mCornerRadii[BlurCorner.TOP_LEFT] = builder.mCornerRadii[BlurCorner.TOP_LEFT]; - mCornerRadii[BlurCorner.TOP_RIGHT] = builder.mCornerRadii[BlurCorner.TOP_RIGHT]; - mCornerRadii[BlurCorner.BOTTOM_LEFT] = builder.mCornerRadii[BlurCorner.BOTTOM_LEFT]; - mCornerRadii[BlurCorner.BOTTOM_RIGHT] = builder.mCornerRadii[BlurCorner.BOTTOM_RIGHT]; - isInvalidate = true; - initCornerRids(); - } - if (builder.mOverlayColor != -1 && mOverlayColor != builder.mOverlayColor) { - mOverlayColor = builder.mOverlayColor; - isInvalidate = true; - } - if (builder.mBlurRadius > 0 && mBlurRadius != builder.mBlurRadius) { - mBlurRadius = builder.mBlurRadius; - mDirty = true; - isInvalidate = true; - } - if (builder.mDownSampleFactor > 0 && mDownSampleFactor != builder.mDownSampleFactor) { - mDownSampleFactor = builder.mDownSampleFactor; - mDirty = true; - isInvalidate = true; - releaseBitmap(); - } - if (isInvalidate) { - invalidate(); - } - } - - public static class Builder { - - // default 4 - private float mDownSampleFactor = -1; - // default #aaffffff - private int mOverlayColor = -1; - // default 10dp (0 < r <= 25) - private float mBlurRadius = -1; - private float mBorderWidth = -1; - private ColorStateList mBorderColor = null; - private int blurMode = -1; - private final float[] mCornerRadii = new float[]{0f, 0f, 0f, 0f}; - private Context mContext; - - private Builder(Context context) { - mContext = context.getApplicationContext(); - } - - /** - * 模糊半径 - * - * @param radius 0~25 - * @return - */ - public Builder setBlurRadius(@FloatRange(from = 0, to = 25) float radius) { - mBlurRadius = radius; - return this; - } - - /** - * 采样率 - * - * @param factor - * @return - */ - public Builder setDownSampleFactor(float factor) { - if (factor <= 0) { - throw new IllegalArgumentException("DownSample factor must be greater than 0."); - } - mDownSampleFactor = factor; - return this; - } - - /** - * 蒙层颜色 - * - * @param color - * @return - */ - public Builder setOverlayColor(int color) { - mOverlayColor = color; - return this; - } - - /** - * Set the corner radius of a specific corner in px. - * 设置圆角 圆形、椭圆无效 - * - * @param corner 枚举类型 对应4个角 - * @param radius 角半径幅度 - * @return - */ - public Builder setCornerRadius(@BlurCorner int corner, float radius) { - mCornerRadii[corner] = radius; - return this; - } - - /** - * Set all the corner radii from a dimension resource id. - * 设置圆角 圆形、椭圆无效 - * - * @param resId dimension resource id of radii. - */ - public Builder setCornerRadiusDimen(@DimenRes int resId) { - float radius = mContext.getResources().getDimension(resId); - return setCornerRadius(radius, radius, radius, radius); - } - - /** - * Set the corner radius of a specific corner in px. - * 设置圆角 圆形、椭圆无效 - * - * @param radius 4个角同值 - */ - public Builder setCornerRadius(float radius) { - return setCornerRadius(radius, radius, radius, radius); - } - - /** - * Set the corner radius of a specific corner in px. - * 设置圆角 圆形、椭圆无效 - */ - public Builder setCornerRadius(float topLeft, float topRight, float bottomLeft, float bottomRight) { - mCornerRadii[BlurCorner.TOP_LEFT] = topLeft; - mCornerRadii[BlurCorner.TOP_RIGHT] = topRight; - mCornerRadii[BlurCorner.BOTTOM_LEFT] = bottomLeft; - mCornerRadii[BlurCorner.BOTTOM_RIGHT] = bottomRight; - return this; - } - - /** - * 设置边框的宽度 - * - * @param resId - * @return - */ - public Builder setBorderWidth(@DimenRes int resId) { - return setBorderWidth(mContext.getResources().getDimension(resId)); - } - - /** - * 设置边框的宽度 - * - * @param width 转px值 - * @return - */ - public Builder setBorderWidth(float width) { - mBorderWidth = width; - return this; - } - - /** - * 设置边框颜色 - * - * @param color R.color.xxxx - * @return - */ - public Builder setBorderColor(@ColorRes int color) { - return setBorderColor(ColorStateList.valueOf(ContextCompat.getColor(mContext, color))); - } - -// public Builder setBorderColor(@ColorInt int color) { -// return setBorderColor(ColorStateList.valueOf(color)); -// } - - public Builder setBorderColor(ColorStateList colors) { - mBorderColor = (colors != null) ? colors : ColorStateList.valueOf(DEFAULT_BORDER_COLOR); - return this; - } - - /** - * 设置高斯模糊的类型 - * - * @param blurMode BlurMode枚举值,支持圆、方形、椭圆(宽高相等椭圆为圆) - * @return - */ - public Builder setBlurMode(@BlurMode int blurMode) { - this.blurMode = blurMode; - return this; - } - - } - - /** - * 建造者模式,避免设置一个参数调用一次重新绘制 - * - * @return - */ - public static Builder build(Context context) { - return new Builder(context); - } - -} diff --git a/blurview/src/main/java/net/center/blurview/enu/BlurCorner.java b/blurview/src/main/java/net/center/blurview/enu/BlurCorner.java deleted file mode 100644 index 943a745..0000000 --- a/blurview/src/main/java/net/center/blurview/enu/BlurCorner.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.center.blurview.enu; - -import androidx.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * @author center - */ -@Retention(RetentionPolicy.SOURCE) -@IntDef({ - BlurCorner.TOP_LEFT, BlurCorner.TOP_RIGHT, - BlurCorner.BOTTOM_LEFT, BlurCorner.BOTTOM_RIGHT -}) -public @interface BlurCorner { - int TOP_LEFT = 0; - int TOP_RIGHT = 1; - int BOTTOM_RIGHT = 2; - int BOTTOM_LEFT = 3; -} diff --git a/blurview/src/main/java/net/center/blurview/enu/BlurMode.java b/blurview/src/main/java/net/center/blurview/enu/BlurMode.java deleted file mode 100644 index d313d92..0000000 --- a/blurview/src/main/java/net/center/blurview/enu/BlurMode.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.center.blurview.enu; - -import androidx.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * @author center - */ -@Retention(RetentionPolicy.SOURCE) -@IntDef({ - BlurMode.MODE_RECTANGLE, BlurMode.MODE_CIRCLE, - BlurMode.MODE_OVAL -}) -public @interface BlurMode { - int MODE_RECTANGLE = 0; - int MODE_CIRCLE = 1; - int MODE_OVAL = 2; -} diff --git a/blurview/src/main/java/net/center/blurview/impl/AndroidStockBlurImpl.java b/blurview/src/main/java/net/center/blurview/impl/AndroidStockBlurImpl.java deleted file mode 100644 index 8e43b63..0000000 --- a/blurview/src/main/java/net/center/blurview/impl/AndroidStockBlurImpl.java +++ /dev/null @@ -1,81 +0,0 @@ -package net.center.blurview.impl; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.graphics.Bitmap; -import android.os.Build; -import android.renderscript.Allocation; -import android.renderscript.Element; -import android.renderscript.RenderScript; -import android.renderscript.ScriptIntrinsicBlur; - -@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) -public class AndroidStockBlurImpl implements BlurImpl { - private RenderScript mRenderScript; - private ScriptIntrinsicBlur mBlurScript; - private Allocation mBlurInput, mBlurOutput; - - @Override - public boolean prepare(Context context, Bitmap buffer, float radius) { - if (mRenderScript == null) { - try { - mRenderScript = RenderScript.create(context); - mBlurScript = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript)); - } catch (android.renderscript.RSRuntimeException e) { - if (isDebug(context)) { - throw e; - } else { - // In release mode, just ignore - release(); - return false; - } - } - } - mBlurScript.setRadius(radius); - - mBlurInput = Allocation.createFromBitmap(mRenderScript, buffer, - Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); - mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType()); - - return true; - } - - @Override - public void release() { - if (mBlurInput != null) { - mBlurInput.destroy(); - mBlurInput = null; - } - if (mBlurOutput != null) { - mBlurOutput.destroy(); - mBlurOutput = null; - } - if (mBlurScript != null) { - mBlurScript.destroy(); - mBlurScript = null; - } - if (mRenderScript != null) { - mRenderScript.destroy(); - mRenderScript = null; - } - } - - @Override - public void blur(Bitmap input, Bitmap output) { - mBlurInput.copyFrom(input); - mBlurScript.setInput(mBlurInput); - mBlurScript.forEach(mBlurOutput); - mBlurOutput.copyTo(output); - } - - // android:debuggable="true" in AndroidManifest.xml (auto set by build tool) - static Boolean DEBUG = null; - - static boolean isDebug(Context ctx) { - if (DEBUG == null && ctx != null) { - DEBUG = (ctx.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; - } - return DEBUG.equals(Boolean.TRUE); - } -} diff --git a/blurview/src/main/java/net/center/blurview/impl/AndroidXBlurImpl.java b/blurview/src/main/java/net/center/blurview/impl/AndroidXBlurImpl.java deleted file mode 100644 index 355c78b..0000000 --- a/blurview/src/main/java/net/center/blurview/impl/AndroidXBlurImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -package net.center.blurview.impl; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.graphics.Bitmap; -import android.renderscript.Allocation; -import android.renderscript.Element; -import android.renderscript.RenderScript; -import android.renderscript.ScriptIntrinsicBlur; - -public class AndroidXBlurImpl implements BlurImpl { - private RenderScript mRenderScript; - private ScriptIntrinsicBlur mBlurScript; - private Allocation mBlurInput, mBlurOutput; - - @Override - public boolean prepare(Context context, Bitmap buffer, float radius) { - if (mRenderScript == null) { - try { - mRenderScript = RenderScript.create(context); - mBlurScript = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript)); - } catch (android.renderscript.RSRuntimeException e) { - if (isDebug(context)) { - throw e; - } else { - // In release mode, just ignore - release(); - return false; - } - } - } - mBlurScript.setRadius(radius); - - mBlurInput = Allocation.createFromBitmap(mRenderScript, buffer, - Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); - mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType()); - - return true; - } - - @Override - public void release() { - if (mBlurInput != null) { - mBlurInput.destroy(); - mBlurInput = null; - } - if (mBlurOutput != null) { - mBlurOutput.destroy(); - mBlurOutput = null; - } - if (mBlurScript != null) { - mBlurScript.destroy(); - mBlurScript = null; - } - if (mRenderScript != null) { - mRenderScript.destroy(); - mRenderScript = null; - } - } - - @Override - public void blur(Bitmap input, Bitmap output) { - mBlurInput.copyFrom(input); - mBlurScript.setInput(mBlurInput); - mBlurScript.forEach(mBlurOutput); - mBlurOutput.copyTo(output); - } - - // android:debuggable="true" in AndroidManifest.xml (auto set by build tool) - static Boolean DEBUG = null; - - static boolean isDebug(Context ctx) { - if (DEBUG == null && ctx != null) { - DEBUG = (ctx.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; - } - return DEBUG.equals(Boolean.TRUE); - } -} diff --git a/blurview/src/main/java/net/center/blurview/impl/BlurImpl.java b/blurview/src/main/java/net/center/blurview/impl/BlurImpl.java deleted file mode 100644 index c2ec996..0000000 --- a/blurview/src/main/java/net/center/blurview/impl/BlurImpl.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.center.blurview.impl; - -import android.content.Context; -import android.graphics.Bitmap; - -public interface BlurImpl { - - boolean prepare(Context context, Bitmap buffer, float radius); - - void release(); - - void blur(Bitmap input, Bitmap output); - -} diff --git a/blurview/src/main/java/net/center/blurview/impl/EmptyBlurImpl.java b/blurview/src/main/java/net/center/blurview/impl/EmptyBlurImpl.java deleted file mode 100644 index 0567c4c..0000000 --- a/blurview/src/main/java/net/center/blurview/impl/EmptyBlurImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.center.blurview.impl; - -import android.content.Context; -import android.graphics.Bitmap; - -public class EmptyBlurImpl implements BlurImpl { - @Override - public boolean prepare(Context context, Bitmap buffer, float radius) { - return false; - } - - @Override - public void release() { - - } - - @Override - public void blur(Bitmap input, Bitmap output) { - - } -} diff --git a/blurview/src/main/java/net/center/blurview/impl/SupportLibraryBlurImpl.java b/blurview/src/main/java/net/center/blurview/impl/SupportLibraryBlurImpl.java deleted file mode 100644 index 3262991..0000000 --- a/blurview/src/main/java/net/center/blurview/impl/SupportLibraryBlurImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -package net.center.blurview.impl; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.graphics.Bitmap; -import android.renderscript.Allocation; -import android.renderscript.Element; -import android.renderscript.RenderScript; -import android.renderscript.ScriptIntrinsicBlur; - -public class SupportLibraryBlurImpl implements BlurImpl { - private RenderScript mRenderScript; - private ScriptIntrinsicBlur mBlurScript; - private Allocation mBlurInput, mBlurOutput; - - @Override - public boolean prepare(Context context, Bitmap buffer, float radius) { - if (mRenderScript == null) { - try { - mRenderScript = RenderScript.create(context); - mBlurScript = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript)); - } catch (android.renderscript.RSRuntimeException e) { - if (isDebug(context)) { - throw e; - } else { - // In release mode, just ignore - release(); - return false; - } - } - } - mBlurScript.setRadius(radius); - - mBlurInput = Allocation.createFromBitmap(mRenderScript, buffer, - Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); - mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType()); - - return true; - } - - @Override - public void release() { - if (mBlurInput != null) { - mBlurInput.destroy(); - mBlurInput = null; - } - if (mBlurOutput != null) { - mBlurOutput.destroy(); - mBlurOutput = null; - } - if (mBlurScript != null) { - mBlurScript.destroy(); - mBlurScript = null; - } - if (mRenderScript != null) { - mRenderScript.destroy(); - mRenderScript = null; - } - } - - @Override - public void blur(Bitmap input, Bitmap output) { - mBlurInput.copyFrom(input); - mBlurScript.setInput(mBlurInput); - mBlurScript.forEach(mBlurOutput); - mBlurOutput.copyTo(output); - } - - // android:debuggable="true" in AndroidManifest.xml (auto set by build tool) - static Boolean DEBUG = null; - - static boolean isDebug(Context ctx) { - if (DEBUG == null && ctx != null) { - DEBUG = (ctx.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; - } - return DEBUG.equals(Boolean.TRUE); - } -} diff --git a/blurview/src/main/res/values/attrs.xml b/blurview/src/main/res/values/attrs.xml deleted file mode 100644 index 1649a09..0000000 --- a/blurview/src/main/res/values/attrs.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file