自定义圆形ImageView

显示头像需要显示圆形头像,RoundImageView继承自ImageView

1.定义属性,在使用RoundImageView时,使用属性设置是圆形还是普通还是使用圆角
在项目的res中的values中选择attrs文件定义属性



    
        
            
            
        
        ssss
    



2.定义继承ImageView,在构造函数中,获取属性
 private fun obtainStyledAttrs(context: Context, attrs: AttributeSet, defStyleAttr: Int) {
        val a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView, defStyleAttr, 0)
        currMode = if (a.hasValue(R.styleable.RoundImageView_type)) a.getInt(R.styleable.RoundImageView_type, MODE_NONE) else MODE_NONE
        currRound = if (a.hasValue(R.styleable.RoundImageView_radius)) a.getDimensionPixelSize(R.styleable.RoundImageView_radius, currRound) else currRound
        a.recycle()   //切记一定要回收
    }

2.重写onDraw方法,对比ImageView的onDraw方法,其实只是添加了一部分if判断是圆角还是圆形:

   override fun onDraw(canvas: Canvas) {
        val mDrawable = drawable
        val mDrawMatrix = imageMatrix
        if (mDrawable == null) {
            return  // couldn't resolve the URI
        }

        if (mDrawable.intrinsicWidth == 0 || mDrawable.intrinsicHeight == 0) {
            return      // nothing to draw (empty bounds)
        }

        if (mDrawMatrix == null && paddingTop == 0 && paddingLeft == 0) {
            mDrawable.draw(canvas)
        } else {
            val saveCount = canvas.saveCount
            canvas.save()

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                if (cropToPadding) {
                    val scrollX = scrollX
                    val scrollY = scrollY
                    canvas.clipRect(scrollX + paddingLeft, scrollY + paddingTop,
                            scrollX + right - left - paddingRight,
                            scrollY + bottom - top - paddingBottom)
                }
            }

            canvas.translate(paddingLeft.toFloat(), paddingTop.toFloat())

            if (currMode == MODE_CIRCLE) {//当为圆形模式的时候,注意此处的代码不是很好,需要再优化,没有判处使用padding的时候,是否能够正常显示,如果在使用padding的时候,会显示不正常。
                val bitmap = drawable2Bitmap(mDrawable)
                mPaint?.setShader(BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP))
                val viewMiniSize = Math.min(width, height)
                val radius = viewMiniSize / 2.5f
                canvas.drawCircle(width / 2.0f, height / 2.0f, radius, mPaint)  //cx:x坐标 cy:y坐标
            } else if (currMode == MODE_ROUND) {//当为圆角模式的时候
                val bitmap = drawable2Bitmap(mDrawable)
                mPaint?.setShader(BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP))
                canvas.drawRoundRect(RectF(paddingLeft.toFloat(), paddingTop.toFloat(), width.toFloat() - paddingRight, height.toFloat() - paddingBottom),
                        currRound.toFloat(), currRound.toFloat(), mPaint)
            } else {
                if (mDrawMatrix != null) {
                    canvas.concat(mDrawMatrix)
                }
                mDrawable.draw(canvas)
            }
            canvas.restoreToCount(saveCount)
        }
    }


重写onMeasure方法:


override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        /**
         * 当模式为圆形模式的时候,我们强制让宽高一致
         */
        if (currMode == MODE_CIRCLE) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
            val result = Math.min(measuredHeight, measuredWidth)
            setMeasuredDimension(result, result)
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        }
    }

3.全部代码
package com.cmbc.creditcard.cmms.view

import android.content.Context
import android.graphics.*
import android.graphics.drawable.Drawable
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.widget.ImageView
import com.cmbc.creditcard.cmms.R


/**
 * Created by Aqua on 2018-07-09.
 * 
* fIREFLY * com.cmbc.creditcard.cmms.view * @author Isan * @date 2018-07-09 15:07 * @version 3.2.1 * @api 6 *
* CMBC-版权所有 *
*/ class RoundImageView : ImageView { /** * 圆形模式 */ private val MODE_CIRCLE = 1 /** * 普通模式 */ private val MODE_NONE = 0 /** * 圆角模式 */ private val MODE_ROUND = 2 private var mPaint: Paint? = null private var currMode = 0 /** * 圆角半径 */ private var currRound = dp2px(10.0f) constructor(context: Context) : super(context) { initViews() } constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { obtainStyledAttrs(context, attrs, 0); initViews() } constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { obtainStyledAttrs(context, attrs, defStyleAttr); initViews() } private fun obtainStyledAttrs(context: Context, attrs: AttributeSet, defStyleAttr: Int) { val a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView, defStyleAttr, 0) currMode = if (a.hasValue(R.styleable.RoundImageView_type)) a.getInt(R.styleable.RoundImageView_type, MODE_NONE) else MODE_NONE currRound = if (a.hasValue(R.styleable.RoundImageView_radius)) a.getDimensionPixelSize(R.styleable.RoundImageView_radius, currRound) else currRound a.recycle() } private fun initViews() { mPaint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG) } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { /** * 当模式为圆形模式的时候,我们强制让宽高一致 */ if (currMode == MODE_CIRCLE) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) val result = Math.min(measuredHeight, measuredWidth) setMeasuredDimension(result, result) } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec) } } override fun onDraw(canvas: Canvas) { val mDrawable = drawable val mDrawMatrix = imageMatrix if (mDrawable == null) { return // couldn't resolve the URI } if (mDrawable.intrinsicWidth == 0 || mDrawable.intrinsicHeight == 0) { return // nothing to draw (empty bounds) } if (mDrawMatrix == null && paddingTop == 0 && paddingLeft == 0) { mDrawable.draw(canvas) } else { val saveCount = canvas.saveCount canvas.save() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (cropToPadding) { val scrollX = scrollX val scrollY = scrollY canvas.clipRect(scrollX + paddingLeft, scrollY + paddingTop, scrollX + right - left - paddingRight, scrollY + bottom - top - paddingBottom) } } canvas.translate(paddingLeft.toFloat(), paddingTop.toFloat()) if (currMode == MODE_CIRCLE) {//当为圆形模式的时候 val bitmap = drawable2Bitmap(mDrawable) mPaint?.setShader(BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)) val viewMiniSize = Math.min(width, height) val radius = viewMiniSize / 2.5f canvas.drawCircle(width / 2.0f, height / 2.0f, radius, mPaint) //cx:x坐标 cy:y坐标 } else if (currMode == MODE_ROUND) {//当为圆角模式的时候 val bitmap = drawable2Bitmap(mDrawable) mPaint?.setShader(BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)) canvas.drawRoundRect(RectF(paddingLeft.toFloat(), paddingTop.toFloat(), width.toFloat() - paddingRight, height.toFloat() - paddingBottom), currRound.toFloat(), currRound.toFloat(), mPaint) } else { if (mDrawMatrix != null) { canvas.concat(mDrawMatrix) } mDrawable.draw(canvas) } canvas.restoreToCount(saveCount) } } /** * drawable转换成bitmap */ private fun drawable2Bitmap(drawable: Drawable?): Bitmap? { if (drawable == null) { return null } val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) //根据传递的scaletype获取matrix对象,设置给bitmap val matrix = imageMatrix if (matrix != null) { canvas.concat(matrix) } drawable.draw(canvas) return bitmap } private fun dp2px(value: Float): Int { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, resources.displayMetrics).toInt() } }
4.使用

 
使用效果

你可能感兴趣的:(自定义圆形ImageView)