使用自定义Screen类绘制图像遇3倍缩放问题及动画需求咨询
解决Bitmap动画显示尺寸放大3倍的问题
看起来你遇到的问题是Android系统根据屏幕密度自动缩放了你的Bitmap资源,导致最终显示的动画帧尺寸超出预期。让我一步步帮你解决这个问题:
问题根源
当你使用BitmapFactory.decodeResource()加载图片时,Android会根据当前设备的屏幕密度(比如xxhdpi设备是3倍密度因子)自动缩放资源。比如你把335x335的图片放在默认的drawable目录(对应mdpi密度),在xxhdpi设备上解码后,Bitmap会被自动放大到335×3=1005x1005左右。之后你用Bitmap.createBitmap()截取1000x1000的区域,这个截取后的Bitmap实际物理尺寸还是放大后的,所以显示时会比你设定的1000x1000大一圈。
而你用Bitmap.createScaledBitmap()时显示正常,是因为你把放大后的Bitmap又强行缩回到了1000x1000,但这种做法会浪费内存(先放大再缩小),不是最优解。
解决方案
我们需要从解码阶段禁用自动缩放,再按需将原始帧缩放到目标尺寸,同时保留动画功能:
1. 修改Bitmap解码逻辑,禁用自动密度缩放
在加载图片时,使用BitmapFactory.Options关闭系统自动缩放,这样解码出来的Bitmap就是图片的原始尺寸:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; // 关键:禁止系统根据屏幕密度缩放Bitmap Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rose1, options); // 初始化Screen对象 screen = new Screen(originalBitmap, 40, 200, 1000, 1000, 1);
2. 调整Screen构造函数,正确处理动画帧
现在解码后的Bitmap是原始尺寸,我们需要把每个帧缩放到你想要的1000x1000尺寸,再传入动画对象:
public Screen (Bitmap res, int xPos, int yPos, int targetW, int targetH, int numFrames){ super.x = xPos; super.y = yPos; height = targetH; width = targetW; Bitmap [] image = new Bitmap[numFrames]; spritesheet = res; // 计算精灵图中单个原始帧的宽高 int originalFrameWidth = spritesheet.getWidth() / numFrames; int originalFrameHeight = spritesheet.getHeight(); for (int i = 0; i<image.length; i++){ // 1. 从精灵图中截取当前原始帧 Bitmap originalFrame = Bitmap.createBitmap( spritesheet, i * originalFrameWidth, // 帧的起始X坐标 0, // 帧的起始Y坐标 originalFrameWidth, originalFrameHeight ); // 2. 将原始帧缩放到目标宽高 image[i] = Bitmap.createScaledBitmap(originalFrame, width, height, true); // 3. 回收原始帧,避免内存泄漏 if (!originalFrame.isRecycled()) { originalFrame.recycle(); } } animation.setFrames(image); animation.setDelay(10); }
额外注意事项
- 资源目录优化:如果你的图片是为xxhdpi设备设计的,建议把它放在
drawable-xxhdpi目录下,这样系统解码时会自动匹配密度,不需要额外设置inScaled=false,兼容性更好。 - 内存管理:Bitmap是内存大户,记得在不需要使用Bitmap时调用
recycle()释放内存,避免OOM问题。
内容的提问来源于stack exchange,提问作者Radek0582
相关产品推荐
相关产品推荐

