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

news2025/4/21 19:01:26

背景

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

开发环境

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----------------------------------------------------------------------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/520926.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在中国,年收入20W是什么水平?答案扎心了(文末附最新招聘)

最近关于“年薪20万算什么水平&#xff1f;”冲上了热搜。对此&#xff0c;许多网友纷纷表示自己的看法&#xff0c;有的认为这个收入属于中高收入人群了。 因为按照最近某招聘网站发布的《中国企业招聘薪酬报告》来看&#xff0c;今年一季度38城企业平均招聘薪酬为10101元&…

用 ChatGPT 读 Vue3 源码,会怎么样?

前言 ChatGPT 最近十分火爆&#xff0c;今天我也来让 ChatGPT 帮我阅读一下 Vue3 的源代码。 都知道 Vue3 组件有一个 setup函数。那么它内部做了什么呢&#xff0c;今天跟随 ChatGPT 来一探究竟。 实战 setup 函数在什么位置呢&#xff0c;我们不知道他的实现函数名称&…

Ebean 字段别名配置引发语法问题

前言 Ebean 没听过&#xff1f;这里简单给你介绍下&#xff1a;Ebean 是一个 Java ORM&#xff08;Object-Relational Mapping&#xff09;框架&#xff0c;具有以下优势&#xff1a; 简单易用&#xff1a;Ebean 的 API 设计简单易用&#xff0c;可以快速上手&#xff0c;无需…

OpenGL高级-GLSL

引言 我们会讨论一些内建变量(Built-in Variable)、组织着色器输入和输出的新方式以及一个叫做uniform缓冲对象(Uniform Buffer Object)的非常有用的工具。 GLSL的内建变量 着色器是很小的&#xff0c;如果我们需要从当前着色器以外的别的资源里的数据&#xff0c;那么我们就不…

ChatGPT系列学习(1)transformer基本原理讲解

文章目录 1. 简介1.1. 发展史 2. Transformer 整体结构3. 名词解释3.1. token 4. transformer输入4.1. 单词 Embedding4.2. 位置Embedding4.3. Transformer Embedding层实现 5. Attention结构5.1. 简介5.2. Self Attention&#xff08;自注意力机制&#xff09;5.2.1. 简介5.2.…

Python 密码破解指南:20~24

协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【OpenDocCN 饱和式翻译计划】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 收割 SB 的人会被 SB 们封神&#xff0c;试图唤醒 SB 的人是 SB 眼中的 SB。——SB 第三定律 二十、…

HashMap源码和原理

HashMap源码分析 重要变量: Node<K,V>[] table 存放单链表头结点的数组size 存储结点数量threshold 阈值,通过size和threshold比较来做扩容loadFactor 加载因子 重要方法: put(K key, V value) 添加结点get(Object key) 查询结点 单链表Node结点中的一些变量: hash …

《程序员面试金典(第6版)》面试题 16.20. T9键盘(哈希映射,C++)

题目描述 在老式手机上&#xff0c;用户通过数字键盘输入&#xff0c;手机将提供与这些数字相匹配的单词列表。每个数字映射到0至4个字母。给定一个数字序列&#xff0c;实现一个算法来返回匹配单词的列表。你会得到一张含有有效单词的列表。&#xff08;原题链接&#xff09; …

程序的灵魂-数据结构

1、数据结构 程序 数据结构 算法 1.1、何为数据结构? 数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的 数据结构是为了更加方便的管理和使用数据&#xff0c;需要结合具体的业务场景来进行选择 通常情况下&#xff0c;精心选择的数…

爆肝一周,我开源了ChatGPT 中文版接口,官方1:1镜像支持全部 官方接口

这里实现我之前文章承诺承接上文 人人实现ChatGPT自由&#xff0c;手把手教你零撸部署自己聊天私服 现在ChatGPT 提供了api接口 可以让我自己对接去实现我们自己想要gpt应用&#xff0c;但是由于一些原因&#xff0c;国内也不开放接口&#xff0c;所以我就1:1 自己对接了官方…

计算机毕业论文内容参考|基于java的研发部署管理平台的设计与实现

文章目录 导文文章重点摘要前言绪论课题背景国内外现状与趋势课题内容应用程序生命周期管理。相关技术与方法介绍系统分析系统设计系统实现系统测试总结和展望本文总结后续工作展望导文 基于java的研发部署管理平台的设计与实现 文章重点 摘要 本文介绍了基于Java的研发部署管…

UNIAPP实战项目笔记71 订单到支付和生成订单号的前后端交互

UNIAPP实战项目笔记71 订单到支付和生成订单号的前后端交互 思路 购物车页面点击结算 发送请求: 传递商品数据 前端就拿到了订单号进行存储 并且跳转到确认订单页面 后端 生成一个订单,并且返回给前端一个订单号 确认订单页面 点击提交订单 前端 判断是否选择了收货地址 …

QT+OpenCV 编译成功

VSQTOpenCV 真费劲 忙活半天算是有效果了 #include "opencv2/opencv.hpp"; using namespace cv;Demo1::Demo1(QWidget* parent): QMainWindow(parent) {ui.setupUi(this);connect(ui.btn, SIGNAL(clicked()), this, SLOT(Btn1Click())); }void Demo1::Btn1Click() {Q…

如何动态的测试Thrift服务

​RPC协议与Thrift框架 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种通信协议&#xff0c;用于不同的进程或计算机之间进行通信和交互。它允许应用程序在本地或远程计算机上调用另一个应用程序中的函数或方法&#xff0c;就像调用本地函数…

asp.net+sqlserver校园超市进销存管理系统的开发与设计

随校园超市管理系统功能&#xff1a;包括&#xff0c;管理员登录、员工登录&#xff1b;商品信息管理&#xff0c;能够查看商品的基本信息&#xff0c;对商品的基本信息进行修改&#xff1b;员工信息管理&#xff0c;管理员工基本信息&#xff0c;设置与不同的权限&#xff0c;…

【Selenium中】——全栈开发——如桃花来

目录索引 查找元素&#xff1a;查找方法&#xff1a;单个元素查找&#xff1a;多个元素查找&#xff1a;*代码演示&#xff1a;* 元素交互操作&#xff1a;清空文字&#xff1a; 推荐的变量名定义名称&#xff1a;执行JavaScript &#xff1a;滚动页面方法&#xff1a;*滚动到底…

NetCore发布到Docker-局域网

1.说明: 1) 目标&#xff0c;NetCore 项目通过Jenkins发布到局域网的服务器上 2) 单机版的请参考 https://mp.csdn.net/mp_blog/creation/editor/130619862 2.安装插件 Publish Over SSH 1) Dashboard -> Manage Jenkins -> 插件管 2) 安装完之后 2.添加SSH服务器 1) …

【重磅分享】免梯子GPT,教你玩转GPT正确姿势

火了一周的 ChatGPT&#xff0c;xd 不允许还有小伙伴不知道这个东西是什么&#xff1f;简单来说就是&#xff0c;你可以让它扮演任何事物&#xff0c;据说已经有人用它开始了颜色文学创作。因为它太火了&#xff0c;所以&#xff0c;本周特推在几十个带有“chatgpt”的项目中选…

VOC标签格式转yolo格式并划分训练集和测试集

目录 一、了解VOC数据格式 1、Annotations目录 2. JPEGImages目录 二、YOLO格式 三、VOC标签格式转yolo格式并划分训练集和测试集 一、了解VOC数据格式 Pascal VOC数据集下载地址&#xff1a;The PASCAL Visual Object Classes Homepage 介绍一下VOC 数据集下载后的目录结构…

Vue(动画、过渡、动画库)

一、动画 1.使用场景 在插入、更新或者移除DOM元素时候&#xff0c;在合适的时候给元素添加样式类型。 2. 使用 首先在组件style创建出现和离开的动画 然后对动画进行处理&#xff08;命名注意是v-enter-action和v-leave-action&#xff09; 如果name命名在默认标签中使用之后…