You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Picasso变换圆角带边框图片后边缘被裁切的解决方法

解决Android 4.4.2中Picasso圆角边框图片边缘裁切问题

看了你的代码,我发现几个关键问题导致图片边缘被裁切,下面一步步给你修正:

问题分析

  1. 参数调用混乱:你调用getRoundedCornerBitmap时参数顺序完全错了,把圆角半径当成了颜色参数传进去,导致后续绘制逻辑全乱了。
  2. 没给边框留空间:你直接在原图片尺寸上绘制边框,边框画在了图片的边缘,ImageView显示时自然会把边缘的边框切掉。
  3. 整数除法丢精度:计算缩放比例ratio用了int除法,当原图宽度小于屏幕宽度时,比例会变成0,边框和圆角尺寸直接失效。
  4. 边框绘制未适配画笔特性:画笔的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:13:56