使用Canvas绘制后Bitmap被裁剪/缩小的问题求助
问题原因分析
你遇到的图片缩小/裁剪问题,核心原因是:从customView.getDrawable()中获取的Bitmap并非原始图片的尺寸。ZoomageView(继承自ImageView)会根据自身布局尺寸对Drawable进行缩放、适配,此时getDrawable()返回的是经过视图适配后的Bitmap,以此为基础创建新Bitmap并设置回视图,相当于把已经缩放压缩后的图当成了“原图”,最终就会出现视觉上的缩小效果,且无法再继续缩小(因为它已经是当前视图适配后的最小尺寸)。
解决方案
方案1:直接加载原始资源Bitmap(适用于本地图片)
如果你的图片是本地drawable/mipmap资源,直接从资源加载原始尺寸的Bitmap,跳过从View的Drawable中获取的步骤:
public void onBtnClick(View view){ ZoomageView customView = findViewById(R.id.myZoomageView); // 加载原始尺寸的Bitmap(替换R.drawable.your_original_image为你的资源ID) Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_original_image); // 创建可编辑的副本(避免原始Bitmap不可修改的问题) Bitmap tempBitmap = originalBitmap.copy(Bitmap.Config.RGB_565, true); Canvas tempCanvas = new Canvas(tempBitmap); // 绘制线条(这里用原始图的尺寸作为终点,避免超出范围) Paint p = new Paint(); p.setStrokeWidth(50); p.setColor(Color.RED); tempCanvas.drawLine(0, 0, originalBitmap.getWidth(), originalBitmap.getHeight(), p); customView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap)); // 回收原始Bitmap,避免内存泄漏 if (!originalBitmap.isRecycled()) { originalBitmap.recycle(); } }
方案2:提前保存原始Bitmap引用(适用于动态加载的图片,如网络图)
如果图片是网络加载或动态生成的,在首次设置到ZoomageView时,就保存原始Bitmap的全局引用:
// 全局变量保存原始Bitmap private Bitmap mOriginalBitmap; // 初始化ZoomageView时保存原始Bitmap public void initZoomageView(Bitmap bitmap) { mOriginalBitmap = bitmap; ZoomageView customView = findViewById(R.id.myZoomageView); customView.setImageBitmap(bitmap); } // 点击按钮绘制时使用保存的原始Bitmap public void onBtnClick(View view){ if (mOriginalBitmap == null) return; ZoomageView customView = findViewById(R.id.myZoomageView); Bitmap tempBitmap = mOriginalBitmap.copy(Bitmap.Config.RGB_565, true); Canvas tempCanvas = new Canvas(tempBitmap); Paint p = new Paint(); p.setStrokeWidth(50); p.setColor(Color.RED); tempCanvas.drawLine(0, 0, mOriginalBitmap.getWidth(), mOriginalBitmap.getHeight(), p); customView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap)); }
额外注意事项
- 若需要根据屏幕上的触摸位置绘制线条,需要将ZoomageView的屏幕坐标转换为原始Bitmap的坐标:利用ZoomageView的变换矩阵,调用
Matrix.invert()计算逆矩阵,将屏幕点映射到原始Bitmap的坐标系中。 - 操作Bitmap后及时回收不再使用的实例,避免OOM问题。
内容的提问来源于stack exchange,提问作者Yaman Saran
相关产品推荐
相关产品推荐

