[关闭]
@946898963 2019-10-04T16:39:05.000000Z 字数 5257 阅读 1138

图片的圆角矩形效果

Android学习笔记 Android绘图


建议先阅读:自定义圆角矩形的ImageView

通过Xfermode方式实现

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

此处输入图片的描述

模式 说明
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中主要绘制代码如下:

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

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

示例代码如下所示:

activity_main.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context=".MainActivity"
  8. android:orientation="vertical">
  9. <ImageView
  10. android:id="@+id/iv_round_image_one"
  11. android:layout_margin="5dp"
  12. android:layout_width="84dp"
  13. android:layout_height="48dp"
  14. />
  15. </LinearLayout>

dimens.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <dimen name="round_rect_bitmap_width">84dp</dimen>
  4. <dimen name="round_rect_bitmap_height">48dp</dimen>
  5. </resources>

MainActivity.java:

  1. public class MainActivity extends AppCompatActivity {
  2. private ImageView mImageViewOne;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. mImageViewOne = findViewById(R.id.iv_round_image_one);
  8. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
  9. mImageViewOne.setImageBitmap(RoundRectImageTools.toRoundRectA(bitmap,(int)getResources().getDimension(R.dimen.round_rect_bitmap_width),(int)getResources().getDimension(R.dimen.round_rect_bitmap_height),30));
  10. }
  11. }

实现圆形效果的代码:

  1. public class RoundRectImageTools {
  2. //对图片裁剪成圆形
  3. public static Bitmap toRoundRectA(Bitmap rawBitmap, int widgetWidth,int widgetHeight,int radius) {
  4. Bitmap bitmap = scaleBitmap(rawBitmap, widgetWidth, widgetHeight);
  5. //指定为 ARGB_4444 可以减小图片大小
  6. Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
  7. Canvas canvas = new Canvas(output);
  8. Paint paint = new Paint();
  9. final int color = 0xff424242;
  10. final Rect rect = new Rect(0, 0,bitmap.getWidth(), bitmap.getHeight());
  11. paint.setAntiAlias(true);
  12. canvas.drawARGB(0, 0, 0, 0);
  13. paint.setColor(color);
  14. canvas.drawRoundRect(new RectF(0,0,bitmap.getWidth(),bitmap.getHeight()), radius,radius, paint);
  15. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  16. canvas.drawBitmap(bitmap, rect, rect, paint);
  17. return output;
  18. }
  19. ....
  20. //将头像按比例缩放
  21. private static Bitmap scaleBitmap(Bitmap bitmap,int widgetWidth,int widgetHeight){
  22. //一定要强转成float 不然有可能因为精度不够 出现 scale为0 的错误
  23. float scaleX = (float)widgetWidth/(float)bitmap.getWidth();
  24. float scaleY = (float) widgetHeight / (float) bitmap.getHeight();
  25. Matrix matrix = new Matrix();
  26. matrix.postScale(scaleX, scaleY);
  27. return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
  28. }
  29. }

最终的效果图:
此处输入图片的描述

通过BitmapShader方式实现

所有的绘制圆角的实现,推荐使用这个方法,不仅仅可以帮助我们实现圆角,连部分圆角都可以实现,比如顶部是两个圆角,底部是两个直角的图片。

首先介绍一下BitmapShader这个类,它作为纹理用于绘制一张图。新图可以是纹理图重复/镜像/边缘像素拉伸而绘制成的新图。这个类构造函数很简单,BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY),第一个参数是Bitmap,作为纹理图传入,tileX是指在水平方向上的绘制方式,tileY是指在竖直方向上的绘制方式。TileMode有三种属性,拉伸、重复、镜像。

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

实现圆形效果的代码:

  1. public class RoundImageTools {
  2. ....
  3. //对图片裁剪成圆形
  4. public static Bitmap toRoundRectB(Bitmap rawBitmap, int widgetWidth,int widgetHeight,int radius) {
  5. Bitmap bitmap = scaleBitmap(rawBitmap, widgetWidth, widgetHeight);
  6. // 初始化绘制纹理图
  7. BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  8. //指定为 ARGB_4444 可以减小图片大小
  9. Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
  10. Canvas canvas = new Canvas(output);
  11. // 初始化画笔
  12. Paint paint = new Paint();
  13. paint.setAntiAlias(true);
  14. paint.setShader(bitmapShader);
  15. // 利用画笔将纹理图绘制到画布上面
  16. canvas.drawRoundRect(new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()), radius, radius, paint);
  17. return output;
  18. }
  19. ....
  20. }

通过画布裁剪的方式实现

关于画布裁剪的知识,建议阅读:Canvas的裁剪

  1. public class RoundRectImageTools {
  2. ....
  3. //对图片裁剪成圆形
  4. public static Bitmap toRoundRectC(Bitmap rawBitmap, int widgetWidth,int widgetHeight,int radius) {
  5. Bitmap bitmap = scaleBitmap(rawBitmap, widgetWidth, widgetHeight);
  6. //指定为 ARGB_4444 可以减小图片大小
  7. Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
  8. Canvas canvas = new Canvas(output);
  9. // 初始化画笔
  10. Paint paint = new Paint();
  11. final int color = 0xff424242;
  12. paint.setAntiAlias(true);
  13. canvas.drawARGB(0, 0, 0, 0);
  14. paint.setColor(color);
  15. Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
  16. Path path = new Path();
  17. path.addRoundRect(new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()), radius, radius, Path.Direction.CW);
  18. canvas.clipPath(path, Region.Op.INTERSECT);
  19. // 利用画笔将纹理图绘制到画布上面
  20. canvas.drawBitmap(bitmap,rect,rect,paint);
  21. return output;
  22. }
  23. ....
  24. }

Demo链接:ImageViews

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注