自定义圆形头像CircleImageView

  圆形头像很常用功能,于是想自己写个自定义的圆形的view。搜索了一下,android中可以通过BitmapShader实现这个效果。

这里写图片描述

  BitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置、

  这里我们只关注BitmapShader,构造方法:

  bitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);

  参数1:bitmap

  参数2,参数3:TileMode;

  TileMode的取值有三种:

  CLAMP 拉伸

  REPEAT 重复

  MIRROR 镜像

  如果大家给电脑屏幕设置屏保的时候,如果图片太小,可以选择重复、拉伸、镜像;

  重复:就是横向、纵向不断重复这个bitmap

  镜像:横向不断翻转重复,纵向不断翻转重复;

  拉伸:这个和电脑屏保的模式应该有些不同,这个拉伸的是图片最后的那一个像素;横向的最后一个横行像素,不断的重复,纵项的那一列像素,不断的重复;

首先现在values下新建attrs.xml,自定义属性。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CircleImageView">
        <attr name="mborder_color" format="color"></attr>
        <attr name="mborder_width" format="dimension"></attr>
        <attr name="msrc" format="reference"></attr>
    </declare-styleable>
</resources>

CircleImageView.java

package com.sy.callme.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

import com.sy.callme.R;

/**
 * Created by SY on 2016/5/16.
 */
public class CircleImageView extends View {
    private Bitmap bitmap;
    private int borderWidth;
    private Drawable drawable;
    private int borderColor;
    private int width;
    private int height;
    private Bitmap src;
    private BitmapShader shader;
    private Paint paint;
    private int radius;
    private int circleX;
    private int circleY;
    private Paint borderPaint;


    public CircleImageView(Context context) {
        super(context);
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //获取自定义属性
        TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
        borderColor = type.getColor(R.styleable.CircleImageView_mborder_color, 0);
        borderWidth = type.getDimensionPixelSize(R.styleable.CircleImageView_mborder_width, 2);
        drawable = type.getDrawable(R.styleable.CircleImageView_msrc);
        //转换为bitmap
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        bitmap = bitmapDrawable.getBitmap();

    }

    private int measureHeight(int heightMeasureSpec) {
        int size = MeasureSpec.getSize(heightMeasureSpec);
        int sizeMode = MeasureSpec.getMode(heightMeasureSpec);
        int result = 0;
        if (sizeMode == MeasureSpec.EXACTLY) {
            //如果是精确尺寸就直接返回结果
            result = size;
        } else {
            //不是就尺寸设置最大为200
            result = 200;
            if (sizeMode == MeasureSpec.AT_MOST) {
                //如果是最大尺寸就返回实际尺寸和最大尺寸之中较小的
                result = Math.min(result, size);
            }
        }
        return result;
    }

    private int measureWidth(int widthMeasureSpec) {
        int size = MeasureSpec.getSize(widthMeasureSpec);
        int sizeMode = MeasureSpec.getMode(widthMeasureSpec);
        int result = 0;
        if (sizeMode == MeasureSpec.EXACTLY) {
            //如果是精确尺寸就直接返回结果
            result = size;
        } else {
            //如果是精确尺寸就直接返回结果
            result = 200;
            if (sizeMode == MeasureSpec.AT_MOST) {
                //如果是最大尺寸就返回实际尺寸和最大尺寸之中较小的
                result = Math.min(result, size);
            }
        }
        return result;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = measureWidth(widthMeasureSpec);
        height = measureHeight(heightMeasureSpec);
        width = height = Math.min(width, height);
        initView();//初始化画笔参数
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(circleX, circleY, radius, paint);
        canvas.drawCircle(circleX, circleY, radius, borderPaint);
    }

    private void initView() {

        src = Bitmap.createScaledBitmap(bitmap, width, height, true);
        shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint = new Paint();
        paint.setShader(shader);//设置shader
        radius = (width - borderWidth * 2) / 2;
        circleX = (width) / 2;
        circleY = (height) / 2;

        borderPaint = new Paint();
        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setStrokeWidth(borderWidth);
        borderPaint.setColor(borderColor);
        borderPaint.setStrokeJoin(Paint.Join.ROUND);//接合处的圆滑
        borderPaint.setStrokeCap(Paint.Cap.ROUND);//圆角的笔触
    }

    public void setImageResoure(Drawable drawable) {
        //转换为bitmap
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        bitmap = bitmapDrawable.getBitmap();
        shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint = new Paint();
        paint.setShader(shader);
        requestLayout();
        invalidate();
    }
}

  首先获取自定义属性的值,然后在onMeasure方法里获得控件宽高,initView方法里设置画笔的参数,创建BitmapShader并给paint设置shader。最后在onDraw方法里绘制就可以了。具体使用:
  

<com.sy.callme.view.CircleImageView
        android:id="@+id/c_image"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginTop="20dp"
        android:layout_gravity="center_horizontal"
        app:mborder_color="#ff7700"
        app:mborder_width="3dp"
        app:msrc="@mipmap/touxiang" />

记得使用自定义view的自定义属性需要在布局文件中引入xmlns:app="http://schemas.android.com/apk/res-auto"

参考资料:Android自定义属性时TypedArray的使用方法
     Android学习笔记进阶15之Shader渲染
      Android学习笔记进阶16之BitmapShader
      详解Paint的各种set方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章