Android笔记(三十六):封装一个Matrix从顶部/底部对齐的ImageView

背景

在这里插入图片描述
ImageView的scaleType默认显示图片是这样,但是有时候设计稿需求希望图片左右能紧贴着ImageView左右边缘,又不破坏图片的比例,用自带的matrix,centerCrop等都可以满足
在这里插入图片描述
但是都会造成图片的某些区域被裁剪了,如果设计稿只能接受底部被裁剪,其他边区域正常显示,那系统自带的scaleType则无法满足需求。这时需要自定义新的scaleType来满足设计要求

源码解析

  • 以宽度为基准,计算图片与ImageView的缩放比例
scale = viewWidth.toFloat() / drawableWidth.toFloat()
  • 根据自定义的scale_type,算出图片显示区域,viewHeight / scale为图片显示高度
        var drawableRect: RectF? = null
        if (mCropType == FROM_TOP) {
            drawableRect = RectF(0f, 0f, drawableWidth.toFloat(), viewHeight / scale)
        } else if (mCropType == FROM_BOTTOM) {
            drawableRect = RectF(
                0f,
                drawableHeight - viewHeight / scale,
                drawableWidth.toFloat(),
                drawableHeight.toFloat()
            )
        }
  • 使用setImageMatrix设置图片绘制边界
val viewRect = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())
matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL)
setImageMatrix(matrix)

完整源码

class MatrixImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    companion object {
        const val DEFAULT = 0
        const val FROM_TOP = 1
        const val FROM_BOTTOM = 2
    }
    private var mCropType = DEFAULT

    init {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.MatrixImageView, 0, 0)
        mCropType = ta.getInt(R.styleable.MatrixImageView_scale_type, DEFAULT)
        if (mCropType != DEFAULT) {
            setScaleType(ScaleType.MATRIX)
        }
        ta.recycle()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (mCropType != DEFAULT) {
            setupImageMatrixRect()
        }
    }

    private fun setupImageMatrixRect() {
        if (getDrawable() == null) {
            return
        }
        val matrix = getImageMatrix()
        val scale: Float
        val viewWidth = width - paddingLeft - paddingRight
        val viewHeight = height - paddingLeft - paddingRight
        val drawableWidth = getDrawable().intrinsicWidth
        val drawableHeight = getDrawable().intrinsicHeight

        scale = viewWidth.toFloat() / drawableWidth.toFloat()

        var drawableRect: RectF? = null
        if (mCropType == FROM_TOP) {
            drawableRect = RectF(0f, 0f, drawableWidth.toFloat(), viewHeight / scale)
        } else if (mCropType == FROM_BOTTOM) {
            drawableRect = RectF(
                0f,
                drawableHeight - viewHeight / scale,
                drawableWidth.toFloat(),
                drawableHeight.toFloat()
            )
        }
        val viewRect = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())
        matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL)
        setImageMatrix(matrix)
    }

    fun setCropType(@CropType cropType: Int) {
        if (mCropType != cropType) {
            mCropType = cropType
            setupImageMatrixRect()
            invalidate()
        }
    }

    @IntDef(FROM_TOP, FROM_BOTTOM)
    @Retention(AnnotationRetention.SOURCE)
    annotation class CropType
}
    <declare-styleable name="MatrixImageView">
        <attr name="scale_type">
            <enum name="matrix_top" value="1" />
            <enum name="matrix_bottom" value="2" />
        </attr>
    </declare-styleable>

最终效果

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker desktop运行rabittmq容器,控制台无法访问

docker desktop运行rabittmq容器&#xff0c;控制台无法访问 启动过程&#xff1a;…此处缺略&#xff0c;网上一大堆 原因 原因是在Docker上运行的RabbitMQ&#xff0c;默认情况下是没有启用管理插件和管理页面的 解决办法 使用命令 docker exec -it 容器id /bin/bash 进…

重拾CSS,前端样式精读-媒体查询

前言 本文收录于CSS系列文章中&#xff0c;欢迎阅读指正 说到媒体查询&#xff0c;大家首先想到的可能是有关响应式的知识点&#xff0c;除此之外&#xff0c;它还可以用于条件加载资源&#xff0c;字体大小&#xff0c;图像和视频的优化&#xff0c;用户界面调整等等方面&am…

使用 Grafana api 查询 Datasource 数据

一、使用grafana 的api 接口 官方API 二、生成Api key 点击 Administration -》Users and accss -》Service accounts 进入页面 点击Add service account 创建 service account 点击Add service account token 点击 Generate token , 就可以生成 api key 了 三、进入grafana…

uniapp luch-request 使用教程+响应对象创建

1. 介绍 luch-request 是一个基于 Promise 开发的 uni-app 跨平台、项目级别的请求库。它具有更小的体积、易用的 API 和方便简单的自定义能力。luch-request 支持请求和响应拦截、全局挂载、多个全局配置实例、自定义验证器、文件上传/下载、任务操作、自定义参数以及多拦截器…

革新人脸图片智能修复

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月16日20点46分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文链接 点击开启你的论文编程之旅…

OpenGL ES 文字渲染方式有几种?

在音视频或 OpenGL 开发中,文字渲染是一个高频使用的功能,比如制作一些酷炫的字幕、为视频添加水印、设置特殊字体等等。 实际上 OpenGL 并没有定义渲染文字的方式,所以我们最能想到的办法是:将带有文字的图像上传到纹理,然后进行纹理贴图。 本文分别介绍下在应用层和 C+…

Javaweb-day12(登录认证)

登录功能 登录校验&#xff08;重点&#xff09; 登录校验指的是在服务器接收到浏览器发送过来的请求之后&#xff0c;首先要对这个请求进行校验&#xff0c;先要校验一下用户登录了没有 怎么来实现登录校验的操作呢&#xff1f;具体的实现思路可以分为两部分&#xff1a; 在…

DBeaver中PostgreSQL数据库显示不全的解决方法

本文介绍在DBeaver中&#xff0c;连接PostgreSQL后&#xff0c;数据库显示不全的解决方法。 最近&#xff0c;在DBeaver中连接了本地的PostgreSQL数据库。但是连接后打开这个数据库时发现&#xff0c;其所显示的Databases不全。如下图所示&#xff0c;Databases只显示了一个pos…

计算机视觉 1-8章 (硕士)

文章目录 零、前言1.先行课程&#xff1a;python、深度学习、数字图像处理2.查文献3.环境安装 第一章&#xff1a;概论1.计算机视觉的概念2.机器学习 第二章&#xff1a;图像处理相关基础1.图像的概念2.图像处理3.滤波器4.卷积神经网络CNN5.图像的多层表示&#xff1a;图像金字…

如何使用EasyExcel生成多列表组合填充的复杂Excel示例

作者&#xff1a;Funky_oaNiu 一、&#xff08;需求&#xff09;生成的表格效果&#xff1a;二、搞一个模板文件三、建立对应的表格实体类四、开始填充五、Vue3前端发起请求下载六、官方文档及AI问答 一、&#xff08;需求&#xff09;生成的表格效果&#xff1a; 其中只有顶部…

手机ip地址异常怎么解决

在现代社会中&#xff0c;手机已成为我们日常生活中不可或缺的一部分&#xff0c;无论是工作、学习还是娱乐&#xff0c;都离不开网络的支持。然而&#xff0c;有时我们会遇到手机IP地址异常的问题&#xff0c;这不仅会影响我们的网络体验&#xff0c;还可能带来安全隐患。本文…

Python酷库之旅-第三方库Pandas(218)

目录 一、用法精讲 1021、pandas.DatetimeIndex.inferred_freq属性 1021-1、语法 1021-2、参数 1021-3、功能 1021-4、返回值 1021-5、说明 1021-6、用法 1021-6-1、数据准备 1021-6-2、代码示例 1021-6-3、结果输出 1022、pandas.DatetimeIndex.indexer_at_time方…

基于 CentOS7.6 的 Docker 下载常用的容器(MySQLRedisMongoDB),解决拉取容器镜像失败问题

安装MySQL&Redis&MongoDB mysql选择是8版本&#xff0c;redis是选择4版本、mongoDB选择最新版&#xff0c;也可以根据自己的需要进行下载对应的版本&#xff0c;无非就是容器名:版本号 这样去拉去相关的容器镜像。如果你还不会在服务器中安装 docker&#xff0c;可以查…

讯飞、阿里云、腾讯云:Android 语音合成服务对比选择

在 移动端 接入语音合成方面&#xff0c;讯飞和腾讯云等都是优秀的选择&#xff0c;但各有其特点和优势。咱们的需求是需要支持普通话/英语/法语三种语言&#xff0c;以下是对各个平台的详细比较&#xff1a; 一、讯飞语音合成介绍 与语音听写相反&#xff0c;语音合成是将一段…

设计模式之责任链模式(Chain Of Responsibility)

一、责任链模式介绍 1、责任链模式介绍 职责链模式(chain of responsibility pattern) 定义: 避免将一个请求的发送者与接收者耦合在 一起&#xff0c;让多个对象都有机会处理请求。将接收请求的对象连接成一条链&#xff0c;并且沿着这条链 传递请求&#xff0c;直到有一个对…

游戏引擎学习第12天

视频参考:https://www.bilibili.com/video/BV1yom9YnEWY 这节没讲什么东西&#xff0c;主要是改了一下音频的代码 后面有介绍一些alloc 和malloc,VirtualAlloc 的东西 _alloca 函数&#xff08;或 alloca&#xff09;分配的是栈内存&#xff0c;它的特点是&#xff1a; 生命周…

更改liunx的磁盘名称

目录 1. 问题的提出 2. 机器环境说明 3. 解决方法 1. 问题的提出 今天在Linux上部署软件&#xff0c;发现要部署软件的硬盘名称带中文&#xff0c;当访问该磁盘时&#xff0c;中文则被转为长长的一串数字字符串&#xff0c;这很不方便&#xff0c;于是需要将带有中文的磁盘名…

基于Python 和 pyecharts 制作招聘数据可视化分析大屏

在本教程中&#xff0c;我们将展示如何使用 Python 和 pyecharts 库&#xff0c;通过对招聘数据的分析&#xff0c;制作一个交互式的招聘数据分析大屏。此大屏将通过不同类型的图表&#xff08;如柱状图、饼图、词云图等&#xff09;展示招聘行业、职位要求、薪资分布等信息。 …

论文PDF页面无法下载PDF

问题&#xff1a;通常在下载学术论文时&#xff0c;网页命名是PDF页面&#xff0c;但是无法下载PDF&#xff0c;下载的是html网页 解决&#xff1a; mac&#xff1a;按F12打开开发者界面 然后点击源代码/来源选项 然后打开下图所在位置&#xff0c;鼠标右键复制链接&#xff…

Ubuntu24 上安装搜狗输入法

link 首先在终端中依次输入以下代码 sudo apt update sudo apt install fcitx 找到语言支持 在终端中依次输入 sudo cp /usr/share/applications/fcitx.desktop /etc/xdg/autostart/ sudo apt purge ibus 进入网页 搜狗输入法linux-首页​ shurufa.sogou.com/linux 找到刚才下…