Android圆角图片和圆形图片实现总结

更新时间:2016-10-28 14:57:03 点击次数:1854次

1. 概述

       Android研发中经常会遇见圆角或者圆形图片的展示,但是系统中ImageView并不能直接支持,需要我们自己做一些处理,来实现圆角图片或者圆形图片,自己近对这块的实现做了一下总结,看一下几种实现方法。

       种方法,很傻,不太优雅,不推荐这种方法,了解这种方法是因为确实看见有人这么做过。推荐使用第二种方法,重新绘制图片,不仅可以绘制出四角圆角图片,还可以绘制出底部/顶部/左边/右边圆角效果,非常方便。如果想要偷懒,可以直接使用RoundedBitmapDrawable来实现圆角照片效果。而第三种方法,使用CardView控件有很大的局限性,它只在5.0以及以上的系统中有效。

下面就来看一下各种方法的具体情况吧。

2. 图层叠加

图层叠加原理很简单,就是在一张图片上面叠加一层图,覆盖部分,让图片展示成圆角。具体原理可以参考下面这张图。


图-1 图层叠加原理图

看一下布局代码,很简单。

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <FrameLayout  android:layout_width="100dp" android:layout_height="100dp" android:background="@drawable/demo_icon_android_logo"> <ImageView  android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/demo_icon_shader"/> </FrameLayout> </RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

运行结果如下:


图-2 图片叠层运行结果图

       效果还是可以的,但是缺点也很明显,一是要准备两张图片,会增加额外的包体积;二是图片叠加一起,必然导致过度绘制;三是该方法太死板,使用时候要考虑图片大小,控件大小,以及蒙层图圆角锯齿效果,非常不灵活,Java里面不灵活就意味着可用性不强。

       所以这种方法不建议使用,大家作为了解就行。提出这种方法是为了让大家了解一下图层,后面重新绘制过程中,有一种方法逻辑跟这个相似,也是绘制图层叠加,生成圆角图片。

3. 重新绘制

对图片的绘制要特别的注意,有时候可能图片太大需要我们压缩,关于图片压缩大家可以查看这片文章压缩图片。重新绘制图片,将图片绘制成圆角,有三种方法。

从性能上讲并没有太大的区别,但是从使用灵活性上说,个人推荐使用BitmapShader。

       在介绍这三个方法之前,先介绍一下图片的拉伸缩放适配,大多数情况先,要展示图片的控件(ImageView)的长宽和图片的长宽并不是一致的,甚至长宽比都不一致,所以在拿到一张图片时候,大多数情况下需要根据控件的大小对图片进行拉伸缩放处理,有人会问为什么不直接使用ImageView属性scaleType去控制拉伸缩放,这是因为当我们将一个Bitmap绘制成圆角后,再去进行拉伸缩放,圆角可能会变形,所以在Bitmap设置到控件之前就需要对Bitmap进行一下拉伸缩放处理,直接看下面代码。

// 图片根据控件大小等比例缩放拉伸 float widthScale = imageViewWidth * 1.0f / bitmap.getWidth(); float heightScale = imageViewHeight * 1.0f / bitmap.getHeight(); // 设置长宽拉伸缩放比 Matrix matrix = new Matrix();
matrix.setScale(widthScale, heightScale); // 拉伸缩放图片 Bitmap newBt = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注:拉伸缩放也可以在Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)方法中控制,后面会提及到。

3.1 BitmapShader绘制圆角

       所有的绘制圆角的实现,推荐使用这个方法,不仅仅可以帮助我们实现圆角,连部分圆角都可以实现,比如顶部是两个圆角,底部是两个直角的图片。 
       首先介绍一下BitmapShader这个类,它作为纹理用于绘制一张图。新图可以是纹理图重复/镜像/边缘像素拉伸而绘制成的新图。这个类构造函数很简单,BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY),个参数是Bitmap,作为纹理图传入,tileX是指在水平方向上的绘制方式,tileY是指在竖直方向上的绘制方式。TileMode有三种属性,拉伸、重复、镜像。

使用BitmapShader绘制图的时候,是从画布的左上角开始绘制的。我们是使用拉伸的绘制模式,直接来看一下代码,了解处理过程。

/**
 * 利用BitmapShader绘制圆角图片
 *
 * @param bitmap
 *              待处理图片
 * @param outWidth
 *              结果图片宽度,一般为控件的宽度
 * @param outHeight
 *              结果图片高度,一般为控件的高度
 * @param radius
 *              圆角半径大小
 * @return *              结果图片
 */ private Bitmap roundBitmapByShader(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
    } // 初始化缩放比 float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 1.0f / bitmap.getHeight();
    Matrix matrix = new Matrix();
    matrix.setScale(widthScale, heightScale); // 初始化绘制纹理图 BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // 根据控件大小对纹理图进行拉伸缩放处理 bitmapShader.setLocalMatrix(matrix); // 初始化目标bitmap Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888); // 初始化目标画布 Canvas targetCanvas = new Canvas(targetBitmap); // 初始化画笔 Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(bitmapShader); // 利用画笔将纹理图绘制到画布上面 targetCanvas.drawRoundRect(new RectF(0, 0, outWidth, outWidth), radius, radius, paint); return targetBitmap;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

       首先初始化了绘制的纹理图,并对图片进行了拉伸缩放处理,没有用到上面提及的拉伸缩放处理方法是因为BitmapShader本身自带了这个属性,进行设置即可。然后初始化了画布和画笔,将设置画笔绘制的纹理图,画笔在绘制图形时候就不是使用单纯的颜色绘制了。后在利用画笔在画布上面绘制出圆形图片。

       看一下这个方法Canvas.drawRoundRect(RectF rect, float rx, float ry, Paint paint),个参数是指定画布的绘制区域,从画布的左上角开始计算;第二个第三个参数是圆角的x轴/y轴的绘制半径,一般设置成相同的值;第三个就是画笔。

我们看一下运行效果。


图-3 BitmapShader圆角效果图

看起来很简单,但这并不是我推荐使用这种方法的原因,丰富的绘制结果才是,有很多样式可以绘制,讲一个比较简单的,底部两个圆角,顶部两个直角,看一下运行效果图。

我们看一下运行效果。


图-4 BitmapShader底部圆角效果图

已经感觉有点厉害了,先来看代码的实现。

/**
 * 利用BitmapShader绘制底部圆角图片
 *
 * @param bitmap
 *              待处理图片
 * @param outWidth
 *              结果图片宽度,一般为控件的宽度
 * @param outHeight
 *              结果图片高度,一般为控件的高度
 * @param radius
 *              圆角半径大小
 * @return *              结果图片
 */ private Bitmap roundBottomBitmapByShader(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
    } // 初始化缩放比 float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 1.0f / bitmap.getHeight();
    Matrix matrix = new Matrix();
    matrix.setScale(widthScale, heightScale); // 初始化绘制纹理图 BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // 根据控件大小对纹理图进行拉伸缩放处理 bitmapShader.setLocalMatrix(matrix); // 初始化目标bitmap Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888); // 初始化目标画布 Canvas targetCanvas = new Canvas(targetBitmap); // 初始化画笔 Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(bitmapShader); // 利用画笔绘制底部圆角 targetCanvas.drawRoundRect(new RectF(0, outHeight - 2 * radius, outWidth, outWidth), radius, radius, paint); // 利用画笔绘制顶部上面直角部分 targetCanvas.drawRect(new RectF(0, 0, outWidth, outHeight - radius), paint); return targetBitmap;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

       仔细的同学已经发现了,这部分代码和上面很相似,只不过后两句有些不同。对,因为后面两句是对图片的绘制,后输出我们想要的效果。targetCanvas.drawRoundRect()先在底部绘制出圆角的矩形,然后targetCanvas.drawRect()绘制出上面的直角。targetCanvas.drawRoundRect()它在画布上面绘制了图片底部2*radius高度的部分,绘制出的结果是一个高度为2*radius的圆角图片,然后再在画布0到outHeight - radius部分绘制出一个直角矩形,这个直角矩形正好覆盖了之前绘制的圆角图片的上半部分,只露出下面的圆角,此时画布上面呈现出的图像就是刚才运行的效果图,看一下下面的原理图帮助我们理解一下。

我们看一下运行效果。


图-5 Bitmapshader底部圆角原理

是不是有点类似上面提高的图层叠加的原理了,根据各种叠加情况,可以绘制出多种效果,有下面几种(同一个图中圆角半径都相同):

除了这些绘制效果,我们还可以绘制出圆角半径不同的图,在此不做讨论。上述所有的绘制代码在后面会给出工程地址,或者直接点击这里查看

3.2 Xfermode绘制圆角

在使用画笔Paint去绘制东西,当绘制多个图层叠加的时候,有16中模式。效果如下图。


图-6 Xfermode类型效果图
模式 说明
PorterDuff.Mode.CLEAR 所有绘制不会绘制到画布上
PorterDuff.Mode.SRC 显示上层绘制图形
PorterDuff.Mode.DST 显示下层绘制图形
PorterDuff.Mode.SRC_OVER 图形叠加,上层盖住下层
PorterDuff.Mode.DST_OVER 图形叠加,下层盖住上层
PorterDuff.Mode.SRC_IN 显示上层交集部分
PorterDuff.Mode.DST_IN 显示下层交集部分
PorterDuff.Mode.SRC_OUT 显示上层非交集部分
PorterDuff.Mode.DST_OUT 显示下层非交集部分
PorterDuff.Mode.SRC_ATOP 显示下层非交集部分和上层交集部分
PorterDuff.Mode.DST_ATOP 显示下层交集部分与上层非交集部分
PorterDuff.Mode.XOR 去除交集部分
PorterDuff.Mode.DARKEN 交集部分颜色加深
PorterDuff.Mode.LIGHTEN 交集部分颜色变亮
PorterDuff.Mode.MULTIPLY 显示交集部分,颜色混合叠加
PorterDuff.Mode.SCREEN 取两图层全部区域,交集部分变为透明色

官方demo中主要绘制代码如下:

// mDstB是黄色的圆形图bitmap // mSrcB是蓝色的矩形图bitmap canvas.drawBitmap(mDstB, 0, 0, paint);
paint.setXfermode(sModes[i]);
canvas.drawBitmap(mSrcB, 0, 0, paint)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

       可以看到在两个绘制图形过程中,添加Xfermode绘制模式,能够改变两个图的叠加效果,我们主要关注一下SrcIn模式,可以看见,用图层叠加的交集去截取mSrcB图,可以利用这个,想绘制一个圆角的图,然后设置绘制模式,接着绘制一个矩形的图,两者一叠加,正好是用圆角图去截取矩形图,矩形图也就是我们的原图片了。

直接看一下实现代码。

/**
 * 利用Xfermode绘制圆角图片
 *
 * @param bitmap
 *              待处理图片
 * @param outWidth
 *              结果图片宽度,一般为控件的宽度
 * @param outHeight
 *              结果图片高度,一般为控件的高度
 * @param radius
 *              圆角半径大小
 * @return *              结果图片
 */ private Bitmap roundBitmapByXfermode(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
    } // 等比例缩放拉伸 float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 1.0f / bitmap.getHeight();
    Matrix matrix = new Matrix();
    matrix.setScale(widthScale, heightScale);
    Bitmap newBt = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); // 初始化目标bitmap Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(targetBitmap);
    canvas.drawARGB(0, 0, 0, 0);

    Paint paint = new Paint();
    paint.setAntiAlias(true);

    RectF rectF = new RectF(0f, 0f, (float) outWidth, (float) outHeight); // 在画布上绘制圆角图 canvas.drawRoundRect(rectF, radius, radius, paint); // 设置叠加模式 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); // 在画布上绘制原图片 Rect ret = new Rect(0, 0, outWidth, outHeight);
    canvas.drawBitmap(newBt, ret, ret, paint); return targetBitmap;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

后展示一下运行的效果图。


图-7 Xfermode圆角效果图

3.3 RoundedBitmapDrawable绘制圆角

如果你觉得上面两种方法还是好麻烦,肯本不想去搞这些绘制的东西,有没有简单的方法呢?

有!

在V4包中有一个RoundedBitmapDrawable类,专门帮助实现圆角效果。

用法也很简单,看代码。

/**
 * 利用RoundedBitmapDrawable绘制圆角图片
 *
 * @param bitmap
 *              待处理图片
 * @param outWidth
 *              结果图片宽度,一般为控件的宽度
 * @param outHeight
 *              结果图片高度,一般为控件的高度
 * @param radius
 *              圆角半径大小
 * @return *              结果图片
 */ private Drawable roundBitmapByBitmapDrawable(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
    } // 等比例缩放拉伸 float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 1.0f / bitmap.getHeight();
    Matrix matrix = new Matrix();
    matrix.setScale(widthScale, heightScale);
    Bitmap newBt = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); // 绘制圆角 RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(getResources(), newBt);
    dr.setCornerRadius(radius);
    dr.setAntiAlias(true); return dr;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

代码就是三行,初始化,然后设置圆角半径dr.setCornerRadius(),设置边缘平滑dr.setAntiAlias()(这步可以不需要)。运行效果如下。


图-8 RoundedBitmapDrawable圆角效果图

其实去查看dr.setCornerRadius()源代码,会发现它内部就是使用的BitmapShader来绘制圆角效果。官方做了一层封装,使得我们使用起来更加方便。

public void setCornerRadius(float cornerRadius) { if (mCornerRadius == cornerRadius) return;

    mIsCircular = false; if (isGreaterThanZero(cornerRadius)) {
        mPaint.setShader(mBitmapShader);
    } else {
        mPaint.setShader(null);
    }

    mCornerRadius = cornerRadius;
    invalidateSelf();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

4. CardView控件圆角

CardView是官方在V7包中新增的一个控件,继承FrameLayout布局,拥有圆角和阴影属性的控件,既然是新控件,看一下它的一些属性。

比较关注的是cardCornerRadiuscardElevation这两个属性,为了实现圆角图片的效果,将cardElevation属性也就是阴影效果,设置为0dp,看一下具体的布局文件代码。

<android.support.v7.widget.CardView  android:layout_width="@dimen/round_bitmap_width" android:layout_height="@dimen/round_bitmap_width" app:cardCornerRadius="5dp" app:cardElevation="0dp"> <ImageView  android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" android:src="@drawable/demo_icon_android_logo"/> </android.support.v7.widget.CardView>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

CardView作为父布局,容纳ImageView控件。看一下运行效果。


图-9 CardView圆角效果图-5.0系统

这个控件用起来非常偷懒,可惜的是CardView调用了View的setClipToOutline(true)方法来裁边,5.0一下的系统没有这个API,也就是说,5.0以下的系统不会呈现出圆角。


图-10 CardView圆角效果图-4.4系统

虽然这个控件不能帮助我们实现圆角图片的效果,但是给我们提供了一个圆角控件,也能帮助我们解决很多需求场景。

5. 圆形图片的实现

       了解了圆角照片的实现,圆形照片的实现就很简单了。圆形图片需要的是一个正方形的图片,将圆角半径设置为正方形图片边长一半即可。但是有时候,我们拿到的图片是一个矩形,长宽不一样长!!!我们需要对图片做裁剪处理,取矩形中间部分,让它变成一个正方形图片。

BitmapShader为例。

/**
 * 利用BitmapShader绘制底部圆角图片
 *
 * @param bitmap
 *              待处理图片
 * @param edgeWidth
 *              正方形控件大小
 * @param radius
 *              圆角半径大小
 * @return *              结果图片
 */ private Bitmap circleBitmapByShader(Bitmap bitmap, int edgeWidth, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
    } float btWidth = bitmap.getWidth(); float btHeight = bitmap.getHeight(); // 水平方向开始裁剪的位置 float btWidthCutSite = 0; // 竖直方向开始裁剪的位置 float btHeightCutSite = 0; // 裁剪成正方形图片的边长,未拉伸缩放 float squareWidth = 0f; if(btWidth > btHeight) { // 如果矩形宽度大于高度 btWidthCutSite = (btWidth - btHeight) / 2f;
        squareWidth = btHeight;
    } else { // 如果矩形宽度不大于高度 btHeightCutSite = (btHeight - btWidth) / 2f;
        squareWidth = btWidth;
    } // 设置拉伸缩放比 float scale = edgeWidth * 1.0f / squareWidth;
    Matrix matrix = new Matrix();
    matrix.setScale(scale, scale); // 将矩形图片裁剪成正方形并拉伸缩放到控件大小 Bitmap squareBt = Bitmap.createBitmap(bitmap, (int)btWidthCutSite, (int)btHeightCutSite, (int)squareWidth, (int)squareWidth, matrix, true); // 初始化绘制纹理图 BitmapShader bitmapShader = new BitmapShader(squareBt, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // 初始化目标bitmap Bitmap targetBitmap = Bitmap.createBitmap(edgeWidth, edgeWidth, Bitmap.Config.ARGB_8888); // 初始化目标画布 Canvas targetCanvas = new Canvas(targetBitmap); // 初始化画笔 Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(bitmapShader); // 利用画笔绘制圆形图 targetCanvas.drawRoundRect(new RectF(0, 0, edgeWidth, edgeWidth), radius, radius, paint); return targetBitmap;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

裁剪拉伸的逻辑比较复杂,主要是因为图片长宽和正方形边长各种关系复杂导致。将图片处理成正方形图片后,后面代码和切圆角代码基本类似。

后来看一下圆形图片的实现效果。


图-11 BitmapShader圆形效果图

看到这里你会发现,其实圆形图片的实现和圆角图片的实现基本是相同的,了解圆角图片的实现方法,圆形图片的实现自然不在话下。

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!