circle imageview

This commit is contained in:
renhaoting 2025-11-21 10:47:44 +08:00
parent 245870b96c
commit e7bdcef024
4 changed files with 209 additions and 4 deletions

View File

@ -12,7 +12,6 @@ import com.ama.core.architecture.appBase.AppViewsFragment
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
import com.ama.core.architecture.util.setStatusBarDarkFont import com.ama.core.architecture.util.setStatusBarDarkFont
import com.ama.core.common.util.dp import com.ama.core.common.util.dp
import com.gamedog.vididin.databinding.VididinappFeatureHomeFragmentHomeBinding
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlin.getValue import kotlin.getValue
import com.gamedog.vididin.databinding.VididinappFeatureMineFragmentMineBinding as ViewBinding import com.gamedog.vididin.databinding.VididinappFeatureMineFragmentMineBinding as ViewBinding

View File

@ -25,18 +25,21 @@
android:id="@+id/ll_account_container" android:id="@+id/ll_account_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="30dp" android:layout_marginTop="80dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"> android:orientation="vertical">
<com.ama.core.common.widget.roundedimageview.RoundedImageView
<com.ama.core.architecture.widget.CircleImageView
android:id="@+id/avatar_view" android:id="@+id/avatar_view"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="100dp" android:layout_height="100dp"
android:scaleType="centerCrop"
android:background="@color/gray3"
android:src="@mipmap/temp" android:src="@mipmap/temp"
tools:ignore="ContentDescription" /> app:isCircle="true" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView

View File

@ -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()
}
}

View File

@ -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>