circle imageview
This commit is contained in:
parent
245870b96c
commit
e7bdcef024
|
|
@ -12,7 +12,6 @@ import com.ama.core.architecture.appBase.AppViewsFragment
|
|||
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
||||
import com.ama.core.architecture.util.setStatusBarDarkFont
|
||||
import com.ama.core.common.util.dp
|
||||
import com.gamedog.vididin.databinding.VididinappFeatureHomeFragmentHomeBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlin.getValue
|
||||
import com.gamedog.vididin.databinding.VididinappFeatureMineFragmentMineBinding as ViewBinding
|
||||
|
|
|
|||
|
|
@ -25,18 +25,21 @@
|
|||
android:id="@+id/ll_account_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginTop="80dp"
|
||||
android:gravity="center_horizontal"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:orientation="vertical">
|
||||
<com.ama.core.common.widget.roundedimageview.RoundedImageView
|
||||
|
||||
<com.ama.core.architecture.widget.CircleImageView
|
||||
android:id="@+id/avatar_view"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="@color/gray3"
|
||||
android:src="@mipmap/temp"
|
||||
tools:ignore="ContentDescription" />
|
||||
app:isCircle="true" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
package com.ama.core.architecture.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.annotation.AttrRes
|
||||
import com.ama.core.architecture.R
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import androidx.core.graphics.withSave
|
||||
|
||||
class CircleImageView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
@AttrRes defStyleAttr: Int = 0
|
||||
) : View(context, attrs, defStyleAttr) {
|
||||
|
||||
private var bitmap: Bitmap? = null
|
||||
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
isAntiAlias = true
|
||||
isDither = true
|
||||
}
|
||||
private val drawRect = RectF()
|
||||
private var scaleType = ScaleType.CENTER_CROP
|
||||
private var roundRadius = 0f
|
||||
private var isCircle = false
|
||||
private val path = Path()
|
||||
|
||||
enum class ScaleType {
|
||||
FIT_XY, CENTER, CENTER_CROP, CENTER_INSIDE
|
||||
}
|
||||
|
||||
init {
|
||||
attrs?.let { initAttributes(it, defStyleAttr) }
|
||||
setWillNotDraw(false)
|
||||
}
|
||||
|
||||
private fun initAttributes(attrs: AttributeSet, defStyleAttr: Int) {
|
||||
context.withStyledAttributes(
|
||||
attrs, R.styleable.ProtoImageView, defStyleAttr, 0
|
||||
) {
|
||||
|
||||
val srcResource = getResourceId(R.styleable.ProtoImageView_src, 0)
|
||||
if (srcResource != 0) {
|
||||
setImageResource(srcResource)
|
||||
}
|
||||
|
||||
val scaleTypeIndex = getInt(R.styleable.ProtoImageView_imageScaleType, 2)
|
||||
scaleType = ScaleType.values().getOrElse(scaleTypeIndex) { ScaleType.CENTER_CROP }
|
||||
roundRadius = getDimension(R.styleable.ProtoImageView_roundRadius, 0f)
|
||||
isCircle = getBoolean(R.styleable.ProtoImageView_isCircle, false)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
val width = getMeasuredSize(widthMeasureSpec, true)
|
||||
val height = getMeasuredSize(heightMeasureSpec, false)
|
||||
setMeasuredDimension(width, height)
|
||||
}
|
||||
|
||||
private fun getMeasuredSize(measureSpec: Int, isWidth: Boolean): Int {
|
||||
val mode = MeasureSpec.getMode(measureSpec)
|
||||
val size = MeasureSpec.getSize(measureSpec)
|
||||
val intrinsicSize = if (isWidth) {
|
||||
bitmap?.width ?: 0
|
||||
} else {
|
||||
bitmap?.height ?: 0
|
||||
}
|
||||
|
||||
return when (mode) {
|
||||
MeasureSpec.EXACTLY -> size
|
||||
MeasureSpec.AT_MOST -> if (intrinsicSize > size) size else intrinsicSize
|
||||
else -> intrinsicSize
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||
super.onSizeChanged(w, h, oldw, oldh)
|
||||
updateDrawRect()
|
||||
updatePath()
|
||||
}
|
||||
|
||||
private fun updateDrawRect() {
|
||||
val bitmap = this.bitmap ?: return
|
||||
val viewWidth = width - paddingLeft - paddingRight
|
||||
val viewHeight = height - paddingTop - paddingBottom
|
||||
|
||||
drawRect.set(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())
|
||||
|
||||
when (scaleType) {
|
||||
ScaleType.FIT_XY -> {
|
||||
// 默认使用drawRect的完整区域
|
||||
}
|
||||
ScaleType.CENTER -> {
|
||||
val left = (viewWidth - bitmap.width) / 2f
|
||||
val top = (viewHeight - bitmap.height) / 2f
|
||||
drawRect.set(left, top, left + bitmap.width, top + bitmap.height)
|
||||
}
|
||||
ScaleType.CENTER_CROP -> {
|
||||
val scale = Math.max(
|
||||
viewWidth / bitmap.width.toFloat(),
|
||||
viewHeight / bitmap.height.toFloat()
|
||||
)
|
||||
val scaledWidth = bitmap.width * scale
|
||||
val scaledHeight = bitmap.height * scale
|
||||
val left = (viewWidth - scaledWidth) / 2
|
||||
val top = (viewHeight - scaledHeight) / 2
|
||||
drawRect.set(left, top, left + scaledWidth, top + scaledHeight)
|
||||
}
|
||||
ScaleType.CENTER_INSIDE -> {
|
||||
val scale = Math.min(
|
||||
viewWidth / bitmap.width.toFloat(),
|
||||
viewHeight / bitmap.height.toFloat()
|
||||
).coerceAtMost(1f)
|
||||
val scaledWidth = bitmap.width * scale
|
||||
val scaledHeight = bitmap.height * scale
|
||||
val left = (viewWidth - scaledWidth) / 2
|
||||
val top = (viewHeight - scaledHeight) / 2
|
||||
drawRect.set(left, top, left + scaledWidth, top + scaledHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePath() {
|
||||
path.reset()
|
||||
when {
|
||||
isCircle -> {
|
||||
val radius = Math.min(width, height) / 2f
|
||||
path.addCircle(width / 2f, height / 2f, radius, Path.Direction.CW)
|
||||
}
|
||||
roundRadius > 0 -> {
|
||||
path.addRoundRect(
|
||||
RectF(0f, 0f, width.toFloat(), height.toFloat()),
|
||||
roundRadius, roundRadius, Path.Direction.CW
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
path.addRect(0f, 0f, width.toFloat(), height.toFloat(), Path.Direction.CW)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
val bitmap = this.bitmap ?: return
|
||||
|
||||
canvas.withSave {
|
||||
if (isCircle || roundRadius > 0) {
|
||||
clipPath(path)
|
||||
}
|
||||
drawBitmap(bitmap, null, drawRect, paint)
|
||||
}
|
||||
}
|
||||
|
||||
fun setImageResource(resId: Int) {
|
||||
bitmap = BitmapFactory.decodeResource(resources, resId)
|
||||
updateDrawRect()
|
||||
updatePath()
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setImageBitmap(bm: Bitmap) {
|
||||
bitmap = bm
|
||||
updateDrawRect()
|
||||
updatePath()
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setScaleType(scaleType: ScaleType) {
|
||||
this.scaleType = scaleType
|
||||
updateDrawRect()
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setRoundRadius(radius: Float) {
|
||||
this.roundRadius = radius
|
||||
updatePath()
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setCircle(circle: Boolean) {
|
||||
this.isCircle = circle
|
||||
updatePath()
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<declare-styleable name="ProtoImageView" tools:ignore="ResourceName">
|
||||
<attr name="src" format="reference" />
|
||||
<attr name="imageScaleType">
|
||||
<enum name="fitXY" value="0" />
|
||||
<enum name="center" value="1" />
|
||||
<enum name="centerCrop" value="2" />
|
||||
<enum name="centerInside" value="3" />
|
||||
</attr>
|
||||
<attr name="roundRadius" format="dimension" />
|
||||
<attr name="isCircle" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
Loading…
Reference in New Issue