Android|Android 圆角&圆形ImageView
Android圆角、圆形ImageView的实现方式有很多,这应该是最简单的实现方式,通过裁剪画布canvas,但是clipPath()方法不支持抗锯齿,图片边缘会有明显的毛糙感
class XImageView : ImageView {private var currentStyle = 0
private val STYLE_ROUND = 1
private val STYLE_CIRCLE = 2
private var radius = 0f
private val path = Path()
private var rectF: RectF = RectF()constructor(context: Context) : this(context, null)constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initAttr(context, attrs)
}private fun initAttr(context: Context, attrs: AttributeSet?) {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.XImageView)
radius = typedArray.getDimension(R.styleable.XImageView_radius, radius)
currentStyle = typedArray.getInt(R.styleable.XImageView_showType, STYLE_ROUND)
typedArray.recycle()
}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (currentStyle == STYLE_CIRCLE) {
val min = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec))
setMeasuredDimension(min, min)
}
rectF.set(0f, 0f, width.toFloat(), height.toFloat())
}override fun onDraw(canvas: Canvas) {
path.reset()
when (currentStyle) {
STYLE_ROUND -> {
if (radius > 0) {
path.addRoundRect(rectF, radius, radius, Path.Direction.CW)
}
}
STYLE_CIRCLE -> {
val circle = width / 2f
path.addCircle(circle, circle, circle, Path.Direction.CW)
}
}
if (!path.isEmpty) {
canvas.clipPath(path)
}
super.onDraw(canvas)
}
}
【Android|Android 圆角&圆形ImageView】另一种方法是使用图像的 Alpha 合成模式,过程就是先绘制目标图像,也就是图片;再绘制一个圆角矩形或者圆形,这样最终目标图像和原图像重合的区域。
class XImageView : ImageView {private var currentStyle = 0
private val STYLE_ROUND = 1
private val STYLE_CIRCLE = 2
private var radius = 0f
private val path = Path()
private var rectF: RectF = RectF()
private val paint by lazy {
Paint().apply {
isAntiAlias = true
style = Paint.Style.FILL
xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
}
}constructor(context: Context) : this(context, null)constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initAttr(context, attrs)
}private fun initAttr(context: Context, attrs: AttributeSet?) {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.XImageView)
radius = typedArray.getDimension(R.styleable.XImageView_radius, radius)
currentStyle = typedArray.getInt(R.styleable.XImageView_showType, STYLE_ROUND)
typedArray.recycle()
}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (currentStyle == STYLE_CIRCLE) {
val min = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec))
setMeasuredDimension(min, min)
}
rectF.set(0f, 0f, width.toFloat(), height.toFloat())
}override fun onDraw(canvas: Canvas) {
path.reset()
canvas.saveLayer(rectF, null, Canvas.ALL_SAVE_FLAG)
super.onDraw(canvas)
when (currentStyle) {
STYLE_ROUND -> {
if (radius > 0) {
path.addRoundRect(rectF, radius, radius, Path.Direction.CW)
}
}
STYLE_CIRCLE -> {
val circle = width / 2f
path.addCircle(circle, circle, circle, Path.Direction.CW)
}
}
canvas.drawPath(path, paint)
canvas.restore()
}
}
推荐阅读
- Android|Android ClassLoader
- iOS|iOS - 消息流程之动态方法决议 & 消息转发
- 【转】Android6.0权限大全和权限分类
- AtomicStampedReference是怎样解决CAS的ABA问题
- Android|【Android】EditText的简单登录界面设计
- 在android/iOS微信浏览器中自动播放HTML5|在android/iOS微信浏览器中自动播放HTML5 audio(音乐)的2种正确方式
- 程序员|Google又更新了(实战-MergeAdapter,android插件化和热修复区别)
- 程序员|2020最全的BAT大厂面试题整理改版,Android从入门到精通
- 史上最全的Android面试题总结,结尾有福利。
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)