安卓自定义View时,处理canvas缩放引起canvas.drawBitmap画质降低

本文介绍如何在自定义View中通过简单的代码实现整体元素的缩放,并保持良好的图片画质。通过添加抗锯齿和抗模糊设置,确保在不同显示比例下仍能保持清晰的显示效果。

自定义view时,经常会用到图片绘制,canvas.drawBitmap家族可以说是非常常用的API,不过有时候开发中要求我们的控件在某些页面是一个比例,某些页面是另一个显示比例,例如我遇到的,item的角标,噗……又是这个,在主页面是100%显示,在列表页要85%显示。这里写图片描述
对于整体大小的控制,可以想到单独对自定义view里的各个元素宽高属性进行参数控制,但是这样既麻烦,又要写一大堆代码,很少浪费时间,另一个方案就是简单粗暴的对canvas操作,让canvas进行缩放,实现整体大小的改变。
然后我就只加了一行代码,接收一个缩放系数,实现了所需效果,但是问题来了,列表页的item的角标画质降低了,好渣,好吧,这个在之前遇到时是关闭了硬件加速解决的,现在硬件加速本身是关闭的,还要怎样,经过一番搜查,到底是找到了方案,google大神早就有针对这个操作的解决方案,只是没经历过还真不知道这么好用,也是很简单。添加如下两行代码:

     private  PaintFlagsDrawFilter pfd;
    //initView()中
     pfd= new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
     //针对绘制bitmap添加抗锯齿
    mImgPaint.setFilterBitmap(true);
    //ondraw()中
     /**
     * 对canvas设置抗锯齿的滤镜,防止变化canvas引起画质降低
     */
    canvas.setDrawFilter(pfd);
    canvas.drawBitmap(mTagImg,mWidth-mTagImg.getWidth(),0,mImgPaint);

完美解决。

你提供的代码创建了一个 `BitmapShader`,用于在自定义绘制中实现位图平铺或拉伸效果。让我们逐部分解析这段代码的含义和用途。 --- ### 🔍 代码解析: ```java BitmapShader shader = new BitmapShader( Bitmap.createScaledBitmap(bitmap, getWidth() * FACTOR, bitmap.getHeight() * FACTOR, true), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP ); ``` #### ✅ `Bitmap.createScaledBitmap(...)` - **作用**:创建一个缩放后的 `Bitmap`。 - **参数说明**: - `bitmap`:原始位图。 - `getWidth() * FACTOR`:缩放后的宽度,`FACTOR` 是一个你自定义缩放因子(比如 2f 表示放大两倍)。 - `bitmap.getHeight() * FACTOR`:缩放后的高度。 - `true`:是否使用滤镜(抗锯齿),提升画质。 #### ✅ `new BitmapShader(...)`: - **作用**:创建一个基于位图的着色器,用于绘制图形使用该位图进行填充。 - **参数说明**: - 第一个参数:用于填充的位图(这里是缩放后的)。 - 第二个参数:X 轴方向的平铺模式(TileMode)。 - 第三个参数:Y 轴方向的平铺模式(TileMode)。 #### ✅ `Shader.TileMode.CLAMP` - **含义**:当绘制区域大于位图,边缘像素会被拉伸填充。 - 其他常见模式: - `REPEAT`:重复平铺。 - `MIRROR`:镜像平铺。 --- ### 🧠 使用场景: 这段代码常用于自定义 View 的 `onDraw()` 方法中,比如实现一个放大镜、背景纹理、或图案平铺效果。例如: ```java Paint paint = new Paint(); paint.setShader(shader); canvas.drawRect(0, 0, getWidth(), getHeight(), paint); ``` --- ### ⚠️ 性能注意事项: 1. **避免在 onDraw 中频繁创建对象**: - `createScaledBitmap()` 和 `BitmapShader` 都是耗操作。 - 如果 `FACTOR` 是固定值,建议在 `onSizeChanged()` 或初始化处理。 2. **复用 Bitmap**: - 如果 `FACTOR` 动态变化,考虑使用 `BitmapPool`(如 Glide 提供)来管理内存。 3. **及回收 Bitmap**: - 如果你不再需要原始或缩放后的 Bitmap,调用 `recycle()` 回收内存。 --- ### ✅ 示例优化代码: ```java private Bitmap scaledBitmap; private BitmapShader shader; @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (bitmap != null && !bitmap.isRecycled()) { scaledBitmap = Bitmap.createScaledBitmap(bitmap, w * FACTOR, bitmap.getHeight() * FACTOR, true); shader = new BitmapShader(scaledBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } } @Override protected void onDraw(Canvas canvas) { if (shader != null) { Paint paint = new Paint(); paint.setShader(shader); canvas.drawRect(0, 0, getWidth(), getHeight(), paint); } } ``` --- ### ✅ 替代方案(使用 Matrix): 如果你只是想缩放绘制而不创建新 Bitmap,可以使用 `Canvas.drawBitmap(bitmap, matrix, paint)`。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值