(转)【ImageView】自定义ImageView系列(一)——简单圆形图片

    xiaoxiao2021-03-25  102

    原地址:http://www.jianshu.com/p/4f55200cea14

    Android项目开发中经常会遇见需要实现圆角或者圆形的图片功能,如果仅仅使用系统自带的ImageView控件显然无法实现此功能,故通过系列文章的形式由简到繁全方位的介绍一下此功能的实现,巩固一下自身的学习,同时,和广大网友交流分享。

    自定义圆形ImageView.jpg

    作为第一篇文章,今天通过一些简单的代码介绍一下圆形图片功能的初步实现。

    自定义的ImageView控件代码如下,如果拥有一定的Android自定义View基础知识的话,通过查看注释基本上能够看懂实现过程:

    package com.feng.meiya.widget.imageview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class CircleImageView extends ImageView { //基本的三个构造函数 public CircleImageView(Context context) { super(context); } public CircleImageView(Context context, AttributeSet attrs) { super(context, attrs); } public CircleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } //自定义View实现过程中很重要的onDraw绘制图形的方法 @Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); //空值判断,必要步骤,避免由于没有设置src导致的异常错误 if (drawable == null) { return; } //必要步骤,避免由于初始化之前导致的异常错误 if (getWidth() == 0 || getHeight() == 0) { return; } if (!(drawable instanceof BitmapDrawable)) { return; } Bitmap b = ((BitmapDrawable) drawable).getBitmap(); if (null == b) { return; } Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); int w = getWidth(); Bitmap roundBitmap = getCroppedBitmap(bitmap, w); canvas.drawBitmap(roundBitmap, 0, 0, null); } /** * 初始Bitmap对象的缩放裁剪过程 * @param bmp 初始Bitmap对象 * @param radius 圆形图片直径大小 * @return 返回一个圆形的缩放裁剪过后的Bitmap对象 */ public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) { Bitmap sbmp; //比较初始Bitmap宽高和给定的圆形直径,判断是否需要缩放裁剪Bitmap对象 if (bmp.getWidth() != radius || bmp.getHeight() != radius) sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false); else sbmp = bmp; Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight()); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(Color.parseColor("#BAB399")); canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f, sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint); //核心部分,设置两张图片的相交模式,在这里就是上面绘制的Circle和下面绘制的Bitmap paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(sbmp, rect, rect, paint); return output; } }

    其中一个很重要的地方就是Paint.setXfermode(Xfermode xfermode)方法,设置两图的相交模式,这里只作简单的介绍:

    系统提供的Xfermode子类有三个:

    AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

    PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素XOR操作。

    PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

    常用用法如下:

    Canvas canvas = new Canvas(bitmap1); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(mask, 0f, 0f, paint);

    可以简单理解为,canvas原有的图片就是背景,即dst, 新画上去的图片就是前景,即src,这样,不同的Mode展示效果如下:

    PorterDuffXfermode两图相交模式效果

    看完上图大致就能理解本文中自定义ImageView实现圆形图片的原理了,下一篇将以GitHub中比较成熟的开源项目为例介绍一个功能全面、性能优化的CircleImageView控件的实现过程,欢迎关注。

    转载请注明原文地址: https://ju.6miu.com/read-5737.html

    最新回复(0)