android 圆角图片

圆角图片在现在的应用中是比较常见的,比如QQ的头像。网上也有很多优秀的开源库,如CircleImageView等。
圆角图片的原理一般使用的是BitmapSharder

先看一下效果图,绿色的圆角图片的边界。



下面我们来自定义ImageView,实现圆角图片制作。
先简单介绍一下BitmapSharder

Shader used to draw a bitmap as a texture. The bitmap can be repeated or mirrored by setting the tiling mode.

意思是Shader(着色器)把一张位图作为纹理来绘制。可以设置tiling mode来使位图重复或者镜像。
tiling mode有三种
1. CLAMP replicate the edge color if the shader draws outside of its original bounds
2. MIRROR repeat the shader’s image horizontally and vertically, alternating mirror images so that adjacent images always seam
3. REPEAT repeat the shader’s image horizontally and vertically

这里我们用的是CLAMP这个mode。为paint设置着色器之后,paint就能够绘制bitmap。
我们自定义一个叫CircleImageView的view来继承ImageView,然后自定义属性,这里定义三个属性,圆角半径,边缘宽度,边缘颜色。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="myCircleRadius" format="dimension"/>
    <attr name="myBorderWidth" format="dimension"/>
    <attr name="myBorderColor" format="color"/>

    <declare-styleable name="CircleImageView">

        <attr name="myCircleRadius"/>
        <attr name="myBorderWidth"/>
        <attr name="myBorderColor"/>
    </declare-styleable>
</resources>

CircleImageView:

/**
 * Created by Lee
 * Date 2016/3/10
 * Email jon_ly@163.com
 * Blog http://masteryi.me
 */
public class CircleImageView extends ImageView {

    private static final String TAG = "CircleImageView";

    private int radius;//圆角半径
    private int borderWidth;//边缘宽度
    private int bordeCloor;//边缘颜色

    private Paint paint;//用于绘制图片
    private Paint paintBorder;//绘制边缘画笔

    private Bitmap bitmap;
    private BitmapShader shader;//着色器

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

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

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取自定义属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
        radius = typedArray.getDimensionPixelOffset(R.styleable.CircleImageView_myCircleRadius, -1);
        borderWidth = typedArray.getDimensionPixelOffset(R.styleable.CircleImageView_myBorderWidth, 0);
        bordeCloor = typedArray.getColor(R.styleable.CircleImageView_myBorderColor, Color.WHITE);
        typedArray.recycle();

        paint = new Paint();
        paint.setAntiAlias(true);//抗锯齿

        paintBorder = new Paint();
        paintBorder.setAntiAlias(true);//抗锯齿
        paintBorder.setColor(bordeCloor);//设置画笔颜色
//        paint.setStrokeWidth(borderWidth);//设置画笔宽度
    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);
        setShader();
        RectF rectFOutter = new RectF(0, 0, getWidth(), getHeight());
        RectF rectFInner = new RectF(borderWidth, borderWidth, getWidth() - borderWidth, getHeight() - borderWidth);
        if (radius < 0) {
            //绘制圆形图片
            canvas.drawOval(rectFOutter, paintBorder);
            //paint画笔设置了BitmapShader所以用paint绘制出来的是bitmap图像 canvas.drawOval表示绘制椭圆,所以结合起来就是绘制椭圆的bitmap
            canvas.drawOval(rectFInner, paint);
        } else {
            //绘制圆角矩形 原理同上
            canvas.drawRoundRect(rectFOutter, radius, radius, paintBorder);
            canvas.drawRoundRect(rectFInner, radius, radius, paint);
        }
    }

    /**
     * 设置渲染器
     */
    private void setShader() {

        Drawable drawable = getDrawable();
        if (drawable == null) {
            return;
        }
        if (getWidth() == 0 || getHeight() == 0) {
            return;
        }
        bitmap = ((BitmapDrawable) drawable).getBitmap();
        Bitmap b = Bitmap.createScaledBitmap(bitmap, getWidth() - 2 * borderWidth, getHeight() - 2 * borderWidth,
                false);//缩放图片
        shader = new BitmapShader(b, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint.setShader(shader);

    }
}

基本原理如上,两只画笔,一支设置BitmapShader用于绘制圆角图片,一支普通画笔,用于绘制边界。关键步骤都有注释。
上述代码还存在一些不足,如在onDraw中new了对象。虽然显示静态图像的时候不会有什么大问题,不过有时候onDraw会被重复调用很多次,不应该在onDraw中new对象,我现在也没想到什么好办法,希望知道的朋友能够告知。还有就是这里图片统一缩放为跟ImageView大小相同,会使ScaleType属性失效,图片会出现变形。所以,这仅仅是最基本的功能,还有很多需要改进的地方。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值