Android修炼系列(25),解决 ImageView 绘制圆角和 CENTER_CROP 冲突

2,279 阅读1分钟

昨天中秋加班,有个需求中用到一个 ImageView.ScaleType.CENTER_CROP 效果,见下:

ccccc.png

本来以为一行代码的事儿,没想到 setScaleType 不生效,看代码是因为 bitmap 绘制了圆角导致冲突的。也是第一次遇到这个情况,知道了问题,当然就是一通 google,不过网上基本都是 Glide 库与 CENTER_CROP 的方案,在我这里并不适用。所以最后只能按照自己的思路搞了搞,在此记录下,如果你还有更好的方法,欢迎指正:

  1. 将原始 bitmap 直接按照 CENTER_CROP 进行裁剪

  2. 将裁剪后的 bitmap 做圆角处理

  3. ImageView 直接使用最终的 bitmap

代码

我将裁剪方法贴下:

public static Bitmap cropBitmap(Bitmap src, int tagW, int tagH) {
    final int srcW = src.getWidth();
    final int srcH = src.getHeight();
    final float xScale = (float) tagW / srcW;
    final float yScale = (float) tagH / srcH;
    final float scale = Math.max(xScale, yScale);

    final float scaleW = scale * srcW;
    final float scaleH = scale * srcH;
    final float left = (tagW - scaleW) / 2;
    final float top = (tagH - scaleH) / 2;

    final RectF tagRect = new RectF(left, top, left + scaleW, top + scaleH); // 新bitmap裁剪区域
    final Bitmap dst = Bitmap.createBitmap(tagW, tagH, src.getConfig());
    final Canvas canvas = new Canvas(dst);
    canvas.drawBitmap(src, null, tagRect, null);
    return dst;
}

圆角处理方法也提供下:

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float[] rids) {
    try {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth()
                , bitmap.getHeight(), Bitmap.Config.ARGB_4444);
        Canvas canvas = new Canvas(output);
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.BLACK);
        Path path = new Path();
        path.addRoundRect(rectF, rids, Path.Direction.CW); // rids[] 四个角的弧度值
        canvas.drawPath(path, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        final Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        canvas.drawBitmap(bitmap, src, rect, paint);
        return output;
    } catch (OutOfMemoryError outOfMemoryError){
        outOfMemoryError.printStackTrace();
        return bitmap;
    } catch (Exception e) {
        TLog.e(TAG, TLog.USR, e);
        return bitmap;
    }
}

这是使用代码:

private void setRoundBitmap(Bitmap bitmap) {
    Bitmap scaleBitmap = null;
    try {
        // 先裁剪成目标大小
        scaleBitmap = NaviUtil.crop(bitmap, tagImgW, tagImgH);
        float radius = NaviUtil.dp2px(getContext(), 8);
        // float[] 2 个为一组,控制每个弧角
        tagBitmap = NaviUtil.getRoundedCornerBitmap(scaleBitmap,
                new float[] {0.0f, 0.0f, 0.0f, 0.0f
                        , radius, radius, radius, radius});
    } catch (OutOfMemoryError outOfMemoryError) {
        return;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        recycleBitmap(bitmap);
        recycleBitmap(scaleBitmap);
    }
    if (null != mImgView) {
        mImgView.setImageBitmap(tagBitmap);
    }
}

代码就这样了,希望对大家有帮助