美文网首页
Android 自定义View 圆形的头像框

Android 自定义View 圆形的头像框

作者: 濺m | 来源:发表于2017-03-28 14:25 被阅读0次

该自定义View继承自ImageView,该自定义View和ImageView的区别就是ImageView是正方形的,而自定义View是圆形的,园外都是一些透明的背景,因此我们就不需要再重写onMeasure这个方法,直接重写onDraw方法即可。

直接上代码

public class RoundImageView extends ImageView {
    private Context context ;
    private int radius = 0 ;
    private int defaultWidth = 0 , defaultHeight = 0 ;
    public RoundImageView(Context context) {
        super(context);
        this.context = context ;
    }

    public RoundImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context ;
    }

    public RoundImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context ;
    }

    /**

     * 获取裁剪后的圆形图片

     * @param radius 半径

     */
    private Bitmap getRoundBitmap (Bitmap bitmap ,int radius) {
        Bitmap squareBitmap;
        int diameter = radius * 2;//直径
        int x = 0, y = 0;
        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();
        int squareWidth = 0, squareHeight = 0;
        //以bitmap的短的边的标准,截取一个以bitmap的中心为中心的正方形
        if (bitmapWidth > bitmapHeight) {
            x = bitmapWidth / 2 - bitmapHeight / 2;
            y = 0;
            squareHeight = squareWidth = bitmapHeight;
        } else {
            y = bitmapHeight / 2 - bitmapWidth / 2;
            x = 0;
            squareHeight = squareWidth = bitmapWidth;
        }
        squareBitmap = Bitmap.createBitmap(bitmap, x, y, squareWidth, squareHeight);
        //将squareBitmap缩放成diameter的大小
        squareBitmap = Bitmap.createScaledBitmap(squareBitmap, diameter, diameter, false);
        //新建一个bitmap resultbitmap,大小为squareBitmap的大小
        Bitmap resultbitmap = Bitmap.createBitmap(squareBitmap.getWidth(),
                squareBitmap.getHeight(),
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(resultbitmap);
        Paint paint = new Paint();
        //新建一个矩形区域位置为0, 0, squareBitmap.getWidth(),squareBitmap.getHeight()
        Rect rect = new Rect(0, 0, squareBitmap.getWidth(),squareBitmap.getHeight());
        paint.setAntiAlias(true);//设置抗锯齿
        paint.setFilterBitmap(true);//对位图进行滤波处理
        paint.setDither(true);//设置防抖动
        canvas.drawARGB(0, 0, 0, 0);//画背景颜色为透明
        //以(squareBitmap.getWidth() / 2,squareBitmap.getHeight() / 2)为圆心,squareBitmap.getWidth() / 2为半径画圆
        canvas.drawCircle(squareBitmap.getWidth() / 2,
                squareBitmap.getHeight() / 2,
                squareBitmap.getWidth() / 2,
                paint);
        //精髓,因为这句话,canvas原先画的透明背景圆和接下来的squareBitmap重叠部分显示出来
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        //在画布中将squareBitmap画出来
        canvas.drawBitmap(squareBitmap, rect, rect, paint);
        bitmap = null ;
        squareBitmap = null;
        //将画布中的内容返回
        return resultbitmap;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //获取图片
        Drawable drawable = getDrawable() ;
        //如果图片为空,直接放返回
        if (drawable == null)
            return;
        //如果控件的宽高其中一个为0,直接返回
        if (getWidth() == 0 || getHeight() == 0)
            return;
        this.measure(0, 0);
        //如果是.9图也无法显示,直接返回
        if(drawable.getClass() == NinePatchDrawable.class)
            return;
        Bitmap b = ((BitmapDrawable) drawable).getBitmap();
        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
        //获取控件的宽高
        if (defaultWidth == 0) {
            defaultWidth = getWidth();
        }
        if (defaultHeight == 0) {
            defaultHeight = getHeight();
        }
        //半径的等于宽高中较小的一边的一半
        radius = (defaultHeight > defaultWidth ? defaultWidth :defaultHeight )/2;
        Bitmap roundBitmap = getRoundBitmap(bitmap, radius);
        //以控件的中心为中心画出图片
        canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight / 2 - radius, null);
    }
}

重点来说getRoundBitmap 中精髓的那一句

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

在这句话中的PorterDuffXfermode有很多中,他们代表着两张图片相交时的模式,下图可以直观显示他们的不同之处
假设SRC为原图,DST为目标图


PorterDuffXfermode

利用这个我们还可以自定义一些圆形的进度条等等

相关文章

网友评论

      本文标题:Android 自定义View 圆形的头像框

      本文链接:https://www.haomeiwen.com/subject/ozyjottx.html