自定义圆形头像

在Android 开发过程中我们可能遇到比较特殊的需求,我们需要自定义View, 来满足需求。

自定义View的三部曲:1. 首先是自定义View 的属性,2.  onMeasure()方法, 3. onDraw() 方法

本文还结合UIL(图片框架,显示本地和网络加载) 这里不详解这个框架,就是使用它完成相应的功能。后续会出文章就行讲解。

我以创建圆形头像为基础来讲解。我参考了菜鸟窝的视频;

我们先看看图吧!


第一个是显示本地资源图片, 第二个是使用ImageLoad加载了网络图片。

ok,开始我们的代码


1. 属性的创建:

首先在res/values文件目录下创建一个attrs.xml文件, 在创建如下代码。

其中<attr>标签的format属性值代表属性的类型,这个类型值一共有10种,分别是:reference,float,color,dimension,boolean,string,enum,integer,fraction,flag

具体情况请看该博客详解:http://blog.csdn.net/sunny2come/article/details/6996943

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CiecleImageView">
        <attr name="outCiecleColor" format="color"></attr>
        <attr name="outCiecleWidth" format="dimension"></attr>
    </declare-styleable>
</resources>

2.  onMeasure()方法:

 在开始写这个之前我们需要了解一下必要属性

 MeasureSpec的三种模式:
 EXACTLY : 表示设置了MATCH_PARENT或者一个准确的数值,含义是父布局要给子布局一个确切的大小。
 AT_MOST : 表示子布局将被限制在一个最大值之内,通常是子布局设置了wrap_content。
 UNSPECIFIED : 表示子布局想要多大就可以要多大,注:我基本上没有用过

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int width = measureWidthOrHeight(widthMeasureSpec);
        int height = measureWidthOrHeight(heightMeasureSpec);

        mViewWidth = width - (mOutCieCleWidth * 2);
        mViewHeight = height  - (mOutCieCleWidth * 2);

        // 传给系统测量参数
        setMeasuredDimension(width, height);
    }

其中 measureWidthOrHeight 是一个自定的方方用于计算高宽


3. ondraw()方法绘制出来:
<span style="font-size: 24px;"> </span><span style="font-size:12px;">@Override
    protected void onDraw(Canvas canvas) {

        // 加载图片
        loadimg();
        if(mImage != null){

            int min = Math.min(mViewHeight, mViewWidth);
            int ciecleCenter = min/2;   // 半径
            mImage = Bitmap.createScaledBitmap(mImage, min, min, false);

            // 画出一个圆
            canvas.drawCircle(ciecleCenter + mOutCieCleWidth, ciecleCenter + mOutCieCleWidth,
                    ciecleCenter + mOutCieCleWidth, mPaintBorder);

            // 画出一个圆形的Bitmap
            canvas.drawBitmap(createCiecleBitamp(mImage, min), mOutCieCleWidth, mOutCieCleWidth, null);

        }
    }</span>
其中 createCiecleBitamp 用于画出一个圆形的bitmap对象。




 接下来看看,CieCleImageView 的完整代码了 (注: 我将这个头像单独写成一个Library的 module:如何创建请参考我的另外文章:Android Studio 中创建一个Library 的module 和导入一个Library项目) 

该代码是写在了headimglibrary 模块里面,最后我会附上工程项目。


CiecleImageView.java 代码

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * @author zzf
 * @data 16/10/1.
 * @Description
 */
public class CieCleImageView extends ImageView {

    // 外圆的颜色(默认为白色)
    private int mOutCieCleColor = Color.WHITE;
    // 外圆的宽度
    private int mOutCieCleWidth;
    // 背景的画笔
    private Paint mPaintBorder;
    // 控件的高宽
    private int mViewHeight;
    private int mViewWidth;
    // 创建bitmap对象
    private Bitmap mImage;

    public CieCleImageView(Context context) {
        super(context);
        initAttrs(context, null);

    }

    public CieCleImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttrs(context, attrs);
    }

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

    /**
     * 初始化属性
     * @param context
     * @param attrs
     */
    private void initAttrs(Context context, AttributeSet attrs) {

        if(attrs != null){

            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CiecleImageView);
            int len = array.length();
            for (int i = 0; i < len; i++){

                int attr = array.getIndex(i);
                if (attr == R.styleable.CiecleImageView_outCiecleColor) {
                    this.mOutCieCleColor = array.getColor(attr, Color.WHITE);

                } else if (attr == R.styleable.CiecleImageView_outCiecleWidth) {
                    this.mOutCieCleWidth = (int)array.getDimension(attr,5);
                }
            }
        }

        // 创建画笔
        mPaintBorder = new Paint();
        // 设置画笔的颜色
        mPaintBorder.setColor(mOutCieCleColor);
        // 设置画笔为抗锯齿
        mPaintBorder.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int width = measureWidthOrHeight(widthMeasureSpec);
        int height = measureWidthOrHeight(heightMeasureSpec);

        mViewWidth = width - (mOutCieCleWidth * 2);
        mViewHeight = height  - (mOutCieCleWidth * 2);

        // 传给系统测量参数
        setMeasuredDimension(width, height);
    }

    /**
     * 测量
     * MeasureSpec的三种模式:
     * EXACTLY: 表示的我们设置了Match_parent或者一个准确的数值,含义是父布局要给子布局一个确切的大小.
     * AT_MOST: 表示子布局将限制在一个最大值之内,通常是子布局设置了wrap_content
     * UNSPECIFIED:表示子布局想要多大就可以要多大,通常出现在AdapterView中item的heightMode中。
     *
     * @param measureSpec
     * @return
     */
    private int measureWidthOrHeight(int measureSpec) {

        int result = 0;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if(mode == MeasureSpec.EXACTLY){                // 表示我们设置了match_parent,或者是设置了准确的值
            result = size;
        }else{

            result = mViewWidth;
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        // 加载图片
        loadimg();
        if(mImage != null){

            int min = Math.min(mViewHeight, mViewWidth);
            int ciecleCenter = min/2;   // 半径
            mImage = Bitmap.createScaledBitmap(mImage, min, min, false);

            // 画出一个圆
            canvas.drawCircle(ciecleCenter + mOutCieCleWidth, ciecleCenter + mOutCieCleWidth,
                    ciecleCenter + mOutCieCleWidth, mPaintBorder);

            // 画出一个圆形的Bitmap
            canvas.drawBitmap(createCiecleBitamp(mImage, min), mOutCieCleWidth, mOutCieCleWidth, null);

        }
    }

    /**
     * 加载图片
     */
    private void loadimg() {

        BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
        if(bitmapDrawable != null){

            mImage = bitmapDrawable.getBitmap();
        }
    }

    /**
     * 返回一个圆形的bitmap
     * @param mImage
     * @param min
     * @return
     */
    private Bitmap createCiecleBitamp(Bitmap mImage, int min) {

        Bitmap bitmap = null;
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        bitmap = Bitmap.createBitmap(min, min, Bitmap.Config.ARGB_8888);

        // 创建一个画布
        Canvas canvas = new Canvas(bitmap);
        canvas.drawCircle(min/2, min/2, min/2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        // 在画一个bitmap
        canvas.drawBitmap(mImage, 0, 0, paint);

        return bitmap;
    }

    /**
     * 设置外圆的颜色, 代码中定义
     * @param color
     */
    public void setOutCieCleColor(int color){

        if(mPaintBorder != null){

            mPaintBorder.setColor(color);
        }

        // 刷新视图
        this.invalidate();
    }

    /**
     * 外圆的宽度
     * @param outCiecleWidth
     */
    public void setOutCiecleWidth(int outCiecleWidth){

        this.mOutCieCleWidth = outCiecleWidth;
        this.invalidate();
    }
}


 到此就结束了:

下面最附上下载的地址:http://download.csdn.net/detail/zhongzunfa/9644751










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值