关于安卓毛玻璃实现(三)recyclerview静态毛玻璃

简介: 关于安卓毛玻璃实现(三)recyclerview静态毛玻璃

背景

毛玻璃,开发中又爱又恨的一个话题,玩法层出不穷,有动态的,也有静态的。有的是实时模糊,有些只需要模糊一次,本文的毛玻璃实现,就是静态毛玻璃。

开发环境

win 10
as 4+
jdk 1.8

代码

!!!源码在文末!!!

最终效果

在这里插入图片描述

思路

看到上图,首先就要观察有什么要点:
(1)毛玻璃的区域,是与图片“内容连贯”的,就是说,毛玻璃展示内容,和实际内容一致,视觉上就是“局部毛玻璃”的效果。
(2)毛玻璃的形状,看上去,毛玻璃四个角都是圆角,所以,就涉及到毛玻璃展示过程中的圆角绘制。

根据要点,可以总结出,原图,必须要先加载出来,然后设置到ImageView上面,再获取ImageView正在显示的图像(先设置到ImageView,因为会收到其ScaleType属性影响),然后自定义view对获取的图片进行处理即可。

实现

原理说完了,那又要怎么实现呢?列出步骤:
(一)把图片显示在背景控件上面
(二)把背景控件显示后的图片,传入到自定义毛玻璃控件中
(三)通过canvas处理,绘制,显示
下面开始具体描述如何实现:

(一)把图片显示在背景控件上面

这一步就是常规操作了,可以用glide,也可以本地随便搞一个图片设置到背景控件中即可,笔者这里的demo是通过ImageView xml属性配置的。

(二)把背景控件显示后的图片,传入到自定义毛玻璃控件中

这里就涉及到一个“获取显示控件的图片”这一个逻辑,具体的实现代码如下:


    /**
     * 普通截图
     */
    public static void viewSnapShot(View view, ViewSnapListener listener) {
        try {
            //使控件可以进行缓存
            view.setDrawingCacheEnabled(true);
            //获取缓存的 Bitmap
            Bitmap drawingCache = view.getDrawingCache();
            //复制获取的 Bitmap
            drawingCache = Bitmap.createBitmap(drawingCache, 0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
            //关闭视图的缓存
            view.setDrawingCacheEnabled(false);
            view.destroyDrawingCache();
            if (drawingCache != null) {
                if (listener != null) {
                    listener.success(drawingCache);
                }
            } else {
                if (listener != null) {
                    listener.failed("draw cache is null");
                }
            }
        } catch (Exception e) {
            if (listener != null) {
                listener.failed(e.getMessage());
            }
        }
    }

通过该方法,可以获取ImageView控件显示中的图片,并且返回一个bitmap对象给外部了。

(三)通过canvas处理,绘制,显示

这里涉及到自定义view。首先,先看xml设置的布局位置,代码如下:

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="200dp">

            <ImageView
                android:id="@+id/thirdImg"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:scaleType="centerCrop"
                android:src="@drawable/testblur" />

            <com.example.ktdemo.blur.blurwidget.BlurAlignBottomView
                android:id="@+id/ivBlurView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentBottom="true" />

        </RelativeLayout>

可以看到,自定义毛玻璃控件BlurAlignBottomView的宽高是与背景图片显示控件的宽高一样的。

再说核心实现。因为宽高一样,所以处理起来,就简单很多了。
(1)通过clipRect方法,剪裁不需要显示的区域
(2)最后把bitmap高斯模糊后通过canvas画上去

对bitmap进行高斯模糊的代码如下:

    public static Bitmap blur(Context context,int blurRadius, Bitmap srcBitmap) {
        try {
            float radius = Math.min(25,blurRadius);
            radius = Math.max(0,radius);
            Bitmap bitmap = srcBitmap.copy(srcBitmap.getConfig(), true);
            final RenderScript rs = RenderScript.create(context);
            final Allocation input = Allocation.createFromBitmap(rs, srcBitmap,
                    Allocation.MipmapControl.MIPMAP_NONE,
                    Allocation.USAGE_SCRIPT);
            final Allocation output = Allocation.createTyped(rs, input.getType());
            final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
            script.setRadius(radius /* e.g. 3.f */);
            script.setInput(input);
            script.forEach(output);
            output.copyTo(bitmap);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return srcBitmap;
        }
    }

使用原生RenderScript模糊即可。

剪裁显示范围以及绘制bitmap核心代码如下:

            int mesWidth = getMeasuredWidth();
            int mesHeight = getMeasuredHeight();
            float radius = mBlurInfo.getRadius();

            Bitmap mSrcBitmap = mBlurInfo.getSrcBitmap();

            canvas.save();

            canvas.clipRect(0, mesHeight - mBlurInfo.getBlurHeight(), mesWidth, mesHeight);

            RectF canvasRectF = new RectF(0, mesHeight - mBlurInfo.getBlurHeight(), mesWidth, mesHeight);
            Path mPath = new Path();
            mPath.addRoundRect(canvasRectF, radius, radius, Path.Direction.CW);
            canvas.clipPath(mPath);

            Rect bitmapRect = new Rect(0, 0, mesWidth, mesHeight);
            canvas.drawBitmap(mSrcBitmap, null, bitmapRect, null);


            canvas.restore();
        }

总结。实现方式其实用很多,而文中的实现方式,仅仅是众多方法中的一种而已,各位若有更好的方法请在评论区留言。

代码地址
搜索BlurAlignBottomView类

that's all----------------------------------------------------------------------------

目录
相关文章
|
3月前
|
Android开发 开发者 索引
Android实战经验之如何使用DiffUtil提升RecyclerView的刷新性能
本文介绍如何使用 `DiffUtil` 实现 `RecyclerView` 数据集的高效更新,避免不必要的全局刷新,尤其适用于处理大量数据场景。通过定义 `DiffUtil.Callback`、计算差异并应用到适配器,可以显著提升性能。同时,文章还列举了常见错误及原因,帮助开发者避免陷阱。
282 9
|
3月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
81 8
|
4月前
|
存储 Android开发 开发者
Android项目架构设计问题之定义RecyclerView的ViewHolder如何解决
Android项目架构设计问题之定义RecyclerView的ViewHolder如何解决
55 0
|
4月前
|
数据可视化 Java 数据挖掘
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
40 0
|
6月前
|
API Android开发 开发者
`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView
【6月更文挑战第26天】`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView。它提供高效的数据视图复用,优化的布局管理,支持多种布局(如线性、网格),并解耦数据、适配器和视图。RecyclerView的灵活性、性能(如局部刷新和动画支持)和扩展性使其成为现代Android开发的首选,特别是在处理大规模数据集时。
75 2
|
6月前
|
Android开发 Kotlin
Android面试题 之 Kotlin DataBinding 图片加载和绑定RecyclerView
本文介绍了如何在Android中使用DataBinding和BindingAdapter。示例展示了如何创建`MyBindingAdapter`,包含一个`setImage`方法来设置ImageView的图片。布局文件使用`&lt;data&gt;`标签定义变量,并通过`app:image`调用BindingAdapter。在Activity中设置变量值传递给Adapter处理。此外,还展示了如何在RecyclerView的Adapter中使用DataBinding,如`MyAdapter`,在子布局`item.xml`中绑定User对象到视图。关注公众号AntDream阅读更多内容。
106 1
|
6月前
|
XML Java Android开发
Android RecyclerView用代码动态设置item的selector
Android RecyclerView用代码动态设置item的selector
49 0
|
6月前
|
XML Android开发 UED
|
7月前
|
存储 缓存 Android开发
构建高效的Android应用:采用RecyclerView优化列表显示
【4月更文挑战第2天】 在移动开发领域,列表显示是最常见的用户界面组件之一。对于Android平台而言,RecyclerView因其高效、灵活的特点而备受开发者青睐。本文将深入探讨如何利用RecyclerView在Android应用中实现流畅的列表滚动,以及通过各种优化策略来提升性能和用户体验。我们将从基本概念出发,逐步展开如何自定义适配器、视图持有者,以及利用布局管理器来实现复杂的列表布局。此外,还将讨论如何通过异步加载、缓存机制和动态数据更新来进一步优化性能。
105 1
|
7月前
|
缓存 监控 Android开发
Android中的RecyclerView优化策略与实践
【4月更文挑战第5天】本文深入探讨了在安卓开发中,如何针对RecyclerView进行性能优化。通过分析常见的滚动卡顿、内存泄漏等问题,提出了相应的解决方案,并结合实际案例展示了优化过程。文章不仅涵盖了使用RecyclerView时应当遵循的最佳实践,还提供了高级技巧以供进阶开发者参考,旨在帮助读者构建更加流畅和高效的列表显示。