Android Picasso变换圆角带边框图片后边缘被裁切的解决方法
解决Android 4.4.2中Picasso圆角边框图片边缘裁切问题
看了你的代码,我发现几个关键问题导致图片边缘被裁切,下面一步步给你修正:
问题分析
- 参数调用混乱:你调用
getRoundedCornerBitmap时参数顺序完全错了,把圆角半径当成了颜色参数传进去,导致后续绘制逻辑全乱了。 - 没给边框留空间:你直接在原图片尺寸上绘制边框,边框画在了图片的边缘,ImageView显示时自然会把边缘的边框切掉。
- 整数除法丢精度:计算缩放比例
ratio用了int除法,当原图宽度小于屏幕宽度时,比例会变成0,边框和圆角尺寸直接失效。 - 边框绘制未适配画笔特性:画笔的
strokeWidth是从线条中心向两边延伸的,你直接用原矩形绘制,会导致一半边框被裁切。
修正后的代码
第一步:修正Transform方法的参数调用和精度问题
@Override public Bitmap transform(Bitmap source) { // 用float除法避免精度丢失,别用int除法! float ratio = (float) source.getWidth() / mDisplayWidth; float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, Constants.SHAPE_STROKE_WIDTH, mDisplayMetrics) * ratio; float radius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, Constants.SQUARE_RADIUS, mDisplayMetrics) * ratio; int x = (int) (mRectF.left * ratio); int y = (int) (mRectF.top * ratio); int width = (int) ((mRectF.right - mRectF.left) * ratio); int height = (int) ((mRectF.bottom - mRectF.top) * ratio); Bitmap bitmap = Bitmap.createBitmap(source, x, y, width, height); source.recycle(); // 这里要传对参数:图片、边框颜色、圆角半径、边框宽度 // 替换成你实际需要的边框颜色,比如Constants.SHAPE_STROKE_COLOR return getRoundedCornerBitmap(bitmap, Color.parseColor("#CCCCCC"), radius, strokeWidth); } @Override public String key() { return "card_square"; }
第二步:重写getRoundedCornerBitmap方法,预留边框空间
private Bitmap getRoundedCornerBitmap(Bitmap bitmap, int color, float cornerSizePx, float borderSizePx) { // 给边框预留空间:左右上下各加borderSizePx,所以宽高总共加2倍边框宽度 int borderOffset = (int) Math.ceil(borderSizePx * 2); int newWidth = bitmap.getWidth() + borderOffset; int newHeight = bitmap.getHeight() + borderOffset; // 创建包含边框空间的新Bitmap Bitmap output = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); // 图片内容的绘制区域:避开边框的位置 final Rect contentRect = new Rect( (int) Math.ceil(borderSizePx), (int) Math.ceil(borderSizePx), newWidth - (int) Math.ceil(borderSizePx), newHeight - (int) Math.ceil(borderSizePx) ); final RectF contentRectF = new RectF(contentRect); // 初始化画笔,开启抗锯齿 paint.setAntiAlias(true); paint.setColor(0xFFFFFFFF); paint.setStyle(Paint.Style.FILL); // 清空画布背景 canvas.drawARGB(0, 0, 0, 0); // 绘制白色圆角背景,用来显示圆角裁剪效果 canvas.drawRoundRect(contentRectF, cornerSizePx, cornerSizePx, paint); // 绘制原图片,只保留圆角区域内的部分 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, null, contentRect, paint); bitmap.recycle(); // 开始绘制边框 paint.setXfermode(null); // 清除之前的混合模式 paint.setColor(color); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(borderSizePx); // 边框的绘制区域:因为stroke是从中心向外画,所以要把RectF的上下左右各缩半条边框宽度 RectF borderRectF = new RectF( borderSizePx / 2f, borderSizePx / 2f, newWidth - borderSizePx / 2f, newHeight - borderSizePx / 2f ); // 圆角半径要加上半条边框宽度,保证边框和内容的圆角完全对齐 canvas.drawRoundRect(borderRectF, cornerSizePx + borderSizePx / 2f, cornerSizePx + borderSizePx / 2f, paint); return output; }
最后检查ImageView设置
你的ImageView设置adjustViewBounds="true"是对的,它会根据新生成的带边框的Bitmap自动调整大小,不会裁切边框。如果需要固定ImageView尺寸,可以加上android:scaleType="centerInside",确保完整显示整个带边框的图片。
内容的提问来源于stack exchange,提问作者user3509081
相关产品推荐
相关产品推荐

