前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自定义圆形图片控件

自定义圆形图片控件

作者头像
佛系编码
发布2018-05-22 11:39:20
1.1K0
发布2018-05-22 11:39:20
举报
文章被收录于专栏:Android学习之路Android学习之路

自定义圆形ImageView

圆形ImageView在头像显示用的比较普遍了,今天对于实现圆形ImageView做个总结;

主要思路是 重写 onDraw() ;方法有两个:

  • 使用paint的Shader(着色器)将图片印在一个圆的画板上
  • 使用Bitmap创建一个空的Canvas(画板),在画板上画一个圆和显示的图片,paint图像混合模式显示

着色器 方式

不带边框

思路

  • 将图片压缩到和控件的大小一致
  • 创建Bitmap 着色器
  • 创建画笔并设置着色器
  • 使用带有着色器的画笔在画板上画圆
代码语言:javascript
复制
private void drawShader(Canvas canvas) {
    Drawable mDrawable = getDrawable();
    if (mDrawable == null) return;
    if (mDrawable instanceof BitmapDrawable){
        Bitmap bmp = ((BitmapDrawable)mDrawable).getBitmap();
        if (bmp == null) return;
        //图片缩放,参数2 目标宽度,参数3目标高度,参数4 是否过滤
        bmp = Bitmap.createScaledBitmap(bmp,getWidth(),getHeight(),true);
        //着色器
        Shader shader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint = new Paint();
        paint.setShader(shader);
        canvas.drawCircle(getWidth()/2,getWidth()/2,getWidth()/2,paint);
    }
}

效果

无边框效果
无边框效果

加边框

有时候我们需要为头像加上一个圆的边框显得更好看一点,其实这个也很好实现,在绘制图片之前先绘制一个带有颜色的圆,根据边框的大小,将图片缩小一点,这样就将边框显示出来了。

画边框

代码语言:javascript
复制
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(outColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2,paint);

绘制图片 将边框大小空出来 (getWidth()-outWidth*2)/2

代码语言:javascript
复制
private void drawShader(Canvas canvas) {
    Drawable mDrawable = getDrawable();
    if (mDrawable == null) return;
    if (mDrawable instanceof BitmapDrawable){
        Bitmap bmp = ((BitmapDrawable)mDrawable).getBitmap();
        if (bmp == null) return;
        //图片缩放,参数2 目标宽度,参数3目标高度,参数4 是否过滤
        bmp = Bitmap.createScaledBitmap(bmp,getWidth(),getHeight(),true);
        //着色器
        Shader shader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint = new Paint();
        paint.setShader(shader);
        canvas.drawCircle(getWidth()/2,getWidth()/2,(getWidth()-outWidth*2)/2,paint);
    }
}

效果

边框效果
边框效果

着色器方式全部代码

自定义属性 边框颜色和宽度

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CircleImageView">
        <attr name="out_width" format="dimension"></attr>
        <attr name="out_color" format="color"></attr>
    </declare-styleable>
</resources>

重写 onDraw() 绘制图片

代码语言:javascript
复制
package com.skymxc.lesson_36_view_override;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

/**
 * Created by sky-mxc
 */
public class CircleImageView extends ImageView {
    private static final String TAG = "CircleImageView";

    private int outWidth = 2;
    private int outColor = Color.RED;

    private Paint paint;

    public CircleImageView(Context context) {
        this(context,null,0);
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//        canvas.drawColor(Color.YELLOW);
        paint.setColor(outColor);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2,paint);
        drawShader(canvas);

    }

 
    private void drawShader(Canvas canvas) {
        Drawable mDrawable = getDrawable();
        if (mDrawable == null) return;
        if (mDrawable instanceof BitmapDrawable){
            Bitmap bmp = ((BitmapDrawable)mDrawable).getBitmap();
            if (bmp == null) return;
            //图片缩放,参数2 目标宽度,参数3目标高度,参数4 是否过滤
            bmp = Bitmap.createScaledBitmap(bmp,getWidth(),getHeight(),true);
            //着色器
            Shader shader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            paint = new Paint();
            paint.setShader(shader);
            canvas.drawCircle(getWidth()/2,getWidth()/2,(getWidth()-outWidth*2)/2,paint);
        }
    }

    public void initAttrs(AttributeSet attrs){
        TypedArray array = getContext().obtainStyledAttributes(attrs,R.styleable.CircleImageView);
        int len =  array.length();
        for(int i=0;i<len;i++){
            int attr = array.getIndex(i);
            switch (attr){
                case R.styleable.CircleImageView_out_color:
                    this.outColor = array.getColor(attr,Color.GREEN);
                    break;
                case R.styleable.CircleImageView_out_width:
                    this.outWidth = (int) array.getDimension(attr,2);
                    Log.i(TAG, "initAttrs: outWidth="+this.outWidth);
                    break;
            }
        }
        array.recycle();
    }


}

 使用图片混合模式显示

创建 Bitmap 使用图片混合模式 将图片和圆形交叉显示

代码语言:javascript
复制
  private Bitmap getCircleBitmap(){
        Drawable mDrawable = getDrawable();
        if (mDrawable == null) return null;
        if (mDrawable instanceof BitmapDrawable){
            Bitmap bmp = ((BitmapDrawable)mDrawable).getBitmap();
            if (bmp == null) return null;
            paint  = new Paint();
            paint.setAntiAlias(true);
            //创建空的位图
            Bitmap output = Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888);
            //创建画板,以位图进行创建
            Canvas canvas= new Canvas(output);
            //Bitmap就成了 透明的图片
            canvas.drawColor(Color.TRANSPARENT);

            //画一个圆形 和图像大小一致
            paint.setColor(Color.WHITE);
            canvas.drawCircle(output.getWidth()/2,output.getHeight()/2,output.getWidth()/2,paint);

//            //paint 相交模式 必须在 两者中间定义  显示交叉的地方  ;前面是 dst;后面是 src
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//
//            //绘制 Bitmap
            Rect src = new Rect(0,0,bmp.getWidth(),bmp.getHeight());
            RectF dst = new RectF(0,0,output.getWidth(),output.getHeight());
            canvas.drawBitmap(bmp,src,dst,paint);
            return  output;


        }

        return  null;
    }
代码语言:javascript
复制
@Override
protected void onDraw(Canvas canvas) {
      Bitmap bmp=  getCircleBitmap();
       canvas.drawBitmap(bmp,0,0,paint);

}

对于这种方式的实现主要在于 paint 的交叉模式; PorterDuffXfermode

实现的方式有很多种 目前是两种. 未完待续。。。。。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义圆形ImageView
    • 着色器 方式
      • 不带边框
        • 加边框
          • 画边框
          • 绘制图片 将边框大小空出来 (getWidth()-outWidth*2)/2
          • 着色器方式全部代码
          • 自定义属性 边框颜色和宽度
          • 重写 onDraw() 绘制图片
        •  使用图片混合模式显示
        相关产品与服务
        图片处理
        图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档