From 8d74f34b7db81b4da6b71afb14409a13b041dfd9 Mon Sep 17 00:00:00 2001 From: Tamsiree Date: Thu, 26 Mar 2020 16:11:57 +0800 Subject: [PATCH] add TBlurView. --- .../rxdemo/activity/ActivityTCardGallery.kt | 19 +--- .../res/layout/activity_tcard_grallery.xml | 11 ++- .../com/tamsiree/rxkit/RxAnimationTool.kt | 4 +- .../main/java/com/tamsiree/rxkit/TBlurTool.kt | 65 ++++++------- .../java/com/tamsiree/rxui/view/TBlurView.kt | 94 +++++++++++++++++++ RxUI/src/main/res/values/attrs.xml | 7 ++ 6 files changed, 138 insertions(+), 62 deletions(-) create mode 100644 RxUI/src/main/java/com/tamsiree/rxui/view/TBlurView.kt diff --git a/RxDemo/src/main/java/com/tamsiree/rxdemo/activity/ActivityTCardGallery.kt b/RxDemo/src/main/java/com/tamsiree/rxdemo/activity/ActivityTCardGallery.kt index e4a5d237..5b92c9d0 100644 --- a/RxDemo/src/main/java/com/tamsiree/rxdemo/activity/ActivityTCardGallery.kt +++ b/RxDemo/src/main/java/com/tamsiree/rxdemo/activity/ActivityTCardGallery.kt @@ -1,12 +1,9 @@ package com.tamsiree.rxdemo.activity -import android.graphics.BitmapFactory import android.os.Bundle import androidx.recyclerview.widget.LinearLayoutManager import com.tamsiree.rxdemo.R import com.tamsiree.rxdemo.adapter.AdapterCardGallery -import com.tamsiree.rxkit.RxAnimationTool -import com.tamsiree.rxkit.TBlurTool import com.tamsiree.rxkit.interfaces.OnDoIntListener import com.tamsiree.rxkit.view.RxToast import com.tamsiree.rxui.activity.ActivityBase @@ -53,13 +50,9 @@ class ActivityTCardGallery : ActivityBase() { RxToast.normal("选中$intValue") if (mLastPos == intValue) { return - } else if (mLastPos > intValue) { -// tIndicator.moveToLeft() - } else if (mLastPos < intValue) { -// tIndicator.moveToRight() } mLastPos = intValue - notifyBackgroundChange() + blurView.notifyChange(mList[mLastPos]) } }) } @@ -72,14 +65,4 @@ class ActivityTCardGallery : ActivityBase() { recyclerView.adapter?.notifyDataSetChanged() } - private fun notifyBackgroundChange() { - val resId = mList[mLastPos] - blurView?.removeCallbacks(mBlurRunnable) - mBlurRunnable = Runnable { - val bitmap = BitmapFactory.decodeResource(resources, resId) - RxAnimationTool.startSwitchBackgroundAnim(blurView, TBlurTool.getBlurBitmap(blurView?.context, bitmap, 15)) - } - blurView?.postDelayed(mBlurRunnable, 300) - } - } diff --git a/RxDemo/src/main/res/layout/activity_tcard_grallery.xml b/RxDemo/src/main/res/layout/activity_tcard_grallery.xml index fc50f62c..a054193d 100644 --- a/RxDemo/src/main/res/layout/activity_tcard_grallery.xml +++ b/RxDemo/src/main/res/layout/activity_tcard_grallery.xml @@ -20,12 +20,13 @@ android:orientation="vertical" tools:context=".activity.ActivityTCardGallery"> - + app:blurDelayTime="100" + app:blurRadius="15" + app:blurSrc="@drawable/bg_friend" /> + app:selectedDotColor="@color/colorPrimary" /> + \ No newline at end of file diff --git a/RxKit/src/main/java/com/tamsiree/rxkit/RxAnimationTool.kt b/RxKit/src/main/java/com/tamsiree/rxkit/RxAnimationTool.kt index 60b7a701..463999ab 100644 --- a/RxKit/src/main/java/com/tamsiree/rxkit/RxAnimationTool.kt +++ b/RxKit/src/main/java/com/tamsiree/rxkit/RxAnimationTool.kt @@ -272,14 +272,14 @@ object RxAnimationTool { oldBitmapDrawable = ColorDrawable(-0x3d3d3e) } if (oldTransitionDrawable == null) { - oldTransitionDrawable = TransitionDrawable(arrayOf(oldBitmapDrawable, BitmapDrawable(bitmap))) + oldTransitionDrawable = TransitionDrawable(arrayOf(oldBitmapDrawable, BitmapDrawable(RxTool.getContext().resources, bitmap))) oldTransitionDrawable.setId(0, 0) oldTransitionDrawable.setId(1, 1) oldTransitionDrawable.isCrossFadeEnabled = true view.setImageDrawable(oldTransitionDrawable) } else { oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(0), oldBitmapDrawable) - oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(1), BitmapDrawable(bitmap)) + oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(1), BitmapDrawable(RxTool.getContext().resources, bitmap)) } oldTransitionDrawable.startTransition(1000) } diff --git a/RxKit/src/main/java/com/tamsiree/rxkit/TBlurTool.kt b/RxKit/src/main/java/com/tamsiree/rxkit/TBlurTool.kt index e1f295b9..d8de36de 100644 --- a/RxKit/src/main/java/com/tamsiree/rxkit/TBlurTool.kt +++ b/RxKit/src/main/java/com/tamsiree/rxkit/TBlurTool.kt @@ -11,6 +11,9 @@ import android.renderscript.RenderScript.RSMessageHandler import android.renderscript.ScriptIntrinsicBlur import android.widget.ImageView import com.tamsiree.rxkit.RxImageTool.isEmptyBitmap +import kotlin.math.abs +import kotlin.math.max +import kotlin.math.min /** * RenderScript图片高斯模糊 @@ -20,24 +23,23 @@ object TBlurTool { /** * 建议模糊度(在0.0到25.0之间) */ - private const val BLUR_RADIUS = 20 + private const val BLUR_RADIUS = 20f private const val SCALED_WIDTH = 100 private const val SCALED_HEIGHT = 100 @JvmOverloads @JvmStatic - fun blur(imageView: ImageView, bitmap: Bitmap?, radius: Int = BLUR_RADIUS) { + fun blur(imageView: ImageView, bitmap: Bitmap, radius: Float = BLUR_RADIUS) { imageView.setImageBitmap(getBlurBitmap(imageView.context, bitmap, radius)) } @JvmStatic - fun getBlurBitmap(context: Context?, bitmap: Bitmap?): Bitmap { + fun getBlurBitmap(context: Context, bitmap: Bitmap): Bitmap { return getBlurBitmap(context, bitmap, BLUR_RADIUS) } /** * 得到模糊后的bitmap - * thanks http://wl9739.github.io/2016/07/14/教你一分钟实现模糊效果/ * * @param context * @param bitmap @@ -45,9 +47,9 @@ object TBlurTool { * @return */ @JvmStatic - fun getBlurBitmap(context: Context?, bitmap: Bitmap?, radius: Int): Bitmap { + fun getBlurBitmap(context: Context, bitmap: Bitmap, radius: Float): Bitmap { // 将缩小后的图片做为预渲染的图片。 - val inputBitmap = Bitmap.createScaledBitmap(bitmap!!, SCALED_WIDTH, SCALED_HEIGHT, false) + val inputBitmap = Bitmap.createScaledBitmap(bitmap, SCALED_WIDTH, SCALED_HEIGHT, false) // 创建一张渲染后的输出图片。 val outputBitmap = Bitmap.createBitmap(inputBitmap) @@ -62,7 +64,7 @@ object TBlurTool { val tmpOut = Allocation.createFromBitmap(rs, outputBitmap) // 设置渲染的模糊程度, 25f是最大模糊度 - blurScript.setRadius(radius.toFloat()) + blurScript.setRadius(radius) // 设置blurScript对象的输入内存 blurScript.setInput(tmpIn) // 将输出数据保存到输出内存中 @@ -72,17 +74,7 @@ object TBlurTool { tmpOut.copyTo(outputBitmap) return outputBitmap } - /** - * 快速模糊 - * - * 先缩小原图,对小图进行模糊,再放大回原先尺寸 - * - * @param src 源图片 - * @param scale 缩小倍数(0...1) - * @param radius 模糊半径 - * @param recycle 是否回收 - * @return 模糊后的图片 - */ + /** * 快速模糊 * @@ -139,8 +131,8 @@ object TBlurTool { */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @JvmStatic - fun renderScriptBlur(src: Bitmap?, radius: Float): Bitmap? { - var radius = radius + fun renderScriptBlur(src: Bitmap, radius: Float): Bitmap? { + var mRadius = radius if (isEmptyBitmap(src)) return null var rs: RenderScript? = null try { @@ -149,13 +141,13 @@ object TBlurTool { val input = Allocation.createFromBitmap(rs, src, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT) val output = Allocation.createTyped(rs, input.type) val blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)) - if (radius > 25) { - radius = 25.0f - } else if (radius <= 0) { - radius = 1.0f + if (mRadius > 25) { + mRadius = 25.0f + } else if (mRadius <= 0) { + mRadius = 1.0f } blurScript.setInput(input) - blurScript.setRadius(radius) + blurScript.setRadius(mRadius) blurScript.forEach(output) output.copyTo(src) } finally { @@ -173,17 +165,16 @@ object TBlurTool { * @return stackBlur模糊图片 */ @JvmStatic - fun stackBlur(src: Bitmap?, radius: Int, recycle: Boolean): Bitmap? { - val ret: Bitmap? - ret = if (recycle) { + fun stackBlur(src: Bitmap, radius: Int, recycle: Boolean): Bitmap? { + val ret: Bitmap = if (recycle) { src } else { - src!!.copy(src.config, true) + src.copy(src.config, true) } if (radius < 1) { return null } - val w = ret!!.width + val w = ret.width val h = ret.height val pix = IntArray(w * h) ret.getPixels(pix, 0, w, 0, 0, w, h) @@ -204,7 +195,7 @@ object TBlurTool { var yp: Int var yi: Int var yw: Int - val vmin = IntArray(Math.max(w, h)) + val vmin = IntArray(max(w, h)) var divsum = div + 1 shr 1 divsum *= divsum val dv = IntArray(256 * divsum) @@ -240,12 +231,12 @@ object TBlurTool { rinsum = ginsum i = -radius while (i <= radius) { - p = pix[yi + Math.min(wm, Math.max(i, 0))] + p = pix[yi + min(wm, max(i, 0))] sir = stack[i + radius] sir[0] = p and 0xff0000 shr 16 sir[1] = p and 0x00ff00 shr 8 sir[2] = p and 0x0000ff - rbs = r1 - Math.abs(i) + rbs = r1 - abs(i) rsum += sir[0] * rbs gsum += sir[1] * rbs bsum += sir[2] * rbs @@ -275,7 +266,7 @@ object TBlurTool { goutsum -= sir[1] boutsum -= sir[2] if (y == 0) { - vmin[x] = Math.min(x + radius + 1, wm) + vmin[x] = min(x + radius + 1, wm) } p = pix[yw + vmin[x]] sir[0] = p and 0xff0000 shr 16 @@ -315,12 +306,12 @@ object TBlurTool { yp = -radius * w i = -radius while (i <= radius) { - yi = Math.max(0, yp) + x + yi = max(0, yp) + x sir = stack[i + radius] sir[0] = r[yi] sir[1] = g[yi] sir[2] = b[yi] - rbs = r1 - Math.abs(i) + rbs = r1 - abs(i) rsum += r[yi] * rbs gsum += g[yi] * rbs bsum += b[yi] * rbs @@ -354,7 +345,7 @@ object TBlurTool { goutsum -= sir[1] boutsum -= sir[2] if (x == 0) { - vmin[y] = Math.min(y + r1, hm) * w + vmin[y] = min(y + r1, hm) * w } p = x + vmin[y] sir[0] = r[p] diff --git a/RxUI/src/main/java/com/tamsiree/rxui/view/TBlurView.kt b/RxUI/src/main/java/com/tamsiree/rxui/view/TBlurView.kt new file mode 100644 index 00000000..df145a34 --- /dev/null +++ b/RxUI/src/main/java/com/tamsiree/rxui/view/TBlurView.kt @@ -0,0 +1,94 @@ +package com.tamsiree.rxui.view + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.util.AttributeSet +import android.widget.ImageView +import androidx.annotation.IntRange +import androidx.appcompat.widget.AppCompatImageView +import com.tamsiree.rxkit.RxAnimationTool.startSwitchBackgroundAnim +import com.tamsiree.rxkit.TBlurTool +import com.tamsiree.rxkit.TBlurTool.getBlurBitmap +import com.tamsiree.rxui.R + +/** + * @ClassName TBlurImageView + * @Description TODO + * @Author tamsiree + * @Date 20-3-26 下午2:32 + * @Version 1.0 + */ +class TBlurView : AppCompatImageView { + private lateinit var mImageView: ImageView + private var mBlurRunnable: Runnable? = null + + /** + * 模糊度 (0...25f) + */ + @SuppressLint("SupportAnnotationUsage") + @IntRange(from = 0, to = 25) + var blurRadius = 15f + + //模糊View引用的资源ID + var blurSrc = 0 + + /** + * 单位是 ms 毫秒 + */ + var delayTime: Long = 200 + private lateinit var mContext: Context + + constructor(context: Context) : super(context) { + initView(context, null) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initView(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + initView(context, attrs) + } + + private fun initView(context: Context, attrs: AttributeSet?) { + mContext = context + mImageView = this + mImageView.scaleType = ScaleType.CENTER_CROP + //获得这个控件对应的属性。 + val a = context.obtainStyledAttributes(attrs, R.styleable.TBlurView) + try { + //模糊View + blurSrc = a.getResourceId(R.styleable.TBlurView_blurSrc, R.drawable.icon_placeholder) + blurRadius = a.getInteger(R.styleable.TBlurView_blurRadius, 15).toFloat() + delayTime = a.getInteger(R.styleable.TBlurView_blurDelayTime, 200).toLong() + } finally { + //回收这个对象 + a.recycle() + } + if (isInEditMode) { + val bitmap = BitmapFactory.decodeResource(mContext.resources, blurSrc) + mImageView.setImageBitmap(TBlurTool.stackBlur(bitmap, blurRadius.toInt(), true)) + } else { + notifyChange(blurSrc) + } + } + + fun notifyChange(resId: Int) { + blurSrc = resId + removeCallbacks(mBlurRunnable) + mBlurRunnable = Runnable { setBlurImage() } + postDelayed(mBlurRunnable, delayTime) + } + + private fun generateBlurImage(): Bitmap { + val bitmap = BitmapFactory.decodeResource(mContext.resources, blurSrc) + return getBlurBitmap(mContext, bitmap, blurRadius) + } + + private fun setBlurImage() { + startSwitchBackgroundAnim(mImageView, generateBlurImage()) + } + +} \ No newline at end of file diff --git a/RxUI/src/main/res/values/attrs.xml b/RxUI/src/main/res/values/attrs.xml index 8ff741f4..16acd2e2 100644 --- a/RxUI/src/main/res/values/attrs.xml +++ b/RxUI/src/main/res/values/attrs.xml @@ -636,4 +636,11 @@ + + + + + + + \ No newline at end of file