显示头像需要显示圆形头像,RoundImageView继承自ImageView
1.定义属性,在使用RoundImageView时,使用属性设置是圆形还是普通还是使用圆角
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.使用