当前位置: 首页 > article >正文

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>

最终效果

在这里插入图片描述


http://www.kler.cn/a/398915.html

相关文章:

  • Py之pymupdf:基于langchain框架结合pymupdf库实现输出每个PDF页面的文本内容、元数据等
  • 【STM32】USB 简要驱动软件架构图
  • 【C++派生类新增对象的初始化顺序】单继承下派生类新增成员对象的初始化顺序
  • C++ 编程基础(5)类与对象 | 5.8、面向对象五大原则
  • MCU的时钟体系
  • c++调用 c# dll 通过 clr (详细避坑)
  • C#获取指定文件夹下所有文件的两种方式(使用Directory.GetFiles()和Directory.EnumerateFiles()函数)及其区别
  • 自动语音识别(ASR)与文本转语音(TTS)技术的应用与发展
  • 【黑马点评debug日记】redis登录跳转不成功
  • 操作系统学习笔记-5 传输层
  • Embedding的用法
  • SSDT Hook
  • 小程序-基于java+SpringBoot+Vue的校园失物招领系统设计与实现
  • outlook邮箱关闭垃圾邮件——PowerAutomate自动化任务
  • TCP实现网络通信(多进程与多线程版本)
  • 正则表达式语法详解(python)
  • Area-Composition模型部署指南
  • vue 中使用rem布局
  • Pytest-Bdd-Playwright 系列教程(10):配置功能文件路径 优化场景定义
  • AB矩阵秩1乘法,列乘以行
  • AWD脚本编写_1
  • JQuery 基础知识学习(详尽版)2024.11.17
  • 内联函数与普通函数有什么区别?如何定义和使用内联函数?
  • Thinkphp6视图介绍
  • oracle19c开机自启动
  • 洛谷刷题日记||基础篇8