优化圆形progressbar
This commit is contained in:
parent
e1d1dbb2b0
commit
c4855e93cf
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.ama.core.common.widget.DragLayout
|
<com.ama.core.common.widget.DragLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:paddingVertical="7dp"
|
android:paddingVertical="7dp"
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<!--<FrameLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
|
|
@ -56,7 +56,19 @@
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:paddingVertical="7dp"
|
android:paddingVertical="7dp"
|
||||||
/>
|
/>
|
||||||
</FrameLayout>
|
</FrameLayout>-->
|
||||||
|
<com.ama.core.architecture.widget.CircleProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
app:progressColor="@color/progress_green"
|
||||||
|
app:backgroundColor="@color/progress_background"
|
||||||
|
app:progressWidth="2dp"
|
||||||
|
app:centerIcon="@mipmap/home_envelope"
|
||||||
|
app:currentProgress="35"
|
||||||
|
app:maxProgress="100"
|
||||||
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</com.ama.core.common.widget.DragLayout>
|
</com.ama.core.common.widget.DragLayout>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
package com.ama.core.architecture.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.*
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.ama.core.architecture.R
|
||||||
|
import com.ama.core.common.util.dp
|
||||||
|
|
||||||
|
class CircleProgressBar @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : View(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
strokeCap = Paint.Cap.ROUND
|
||||||
|
}
|
||||||
|
|
||||||
|
private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
style = Paint.Style.STROKE
|
||||||
|
strokeCap = Paint.Cap.ROUND
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private var progressWidth = 0f
|
||||||
|
private var progressColor = 0
|
||||||
|
private var backgroundColor = 0
|
||||||
|
private var centerIcon: Bitmap? = null
|
||||||
|
|
||||||
|
private var maxProgress = 100
|
||||||
|
private var currentProgress = 0
|
||||||
|
private var startAngle = -90f
|
||||||
|
|
||||||
|
private val rectF = RectF()
|
||||||
|
private var viewSize = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
initAttributes(attrs, defStyleAttr)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initAttributes(attrs: AttributeSet?, defStyleAttr: Int) {
|
||||||
|
val typedArray = context.obtainStyledAttributes(
|
||||||
|
attrs, R.styleable.CircleProgressBar, defStyleAttr, 0
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取自定义属性
|
||||||
|
progressColor = typedArray.getColor(
|
||||||
|
R.styleable.CircleProgressBar_progressColor,
|
||||||
|
ContextCompat.getColor(context, R.color.progress_green)
|
||||||
|
)
|
||||||
|
|
||||||
|
backgroundColor = typedArray.getColor(
|
||||||
|
R.styleable.CircleProgressBar_backgroundColor,
|
||||||
|
ContextCompat.getColor(context, R.color.progress_background)
|
||||||
|
)
|
||||||
|
|
||||||
|
progressWidth = typedArray.getDimension(
|
||||||
|
R.styleable.CircleProgressBar_progressWidth,
|
||||||
|
dpToPx(2f)
|
||||||
|
)
|
||||||
|
|
||||||
|
val iconRes = typedArray.getResourceId(R.styleable.CircleProgressBar_centerIcon, 0)
|
||||||
|
if (iconRes != 0) {
|
||||||
|
setCenterIcon(iconRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxProgress = typedArray.getInt(R.styleable.CircleProgressBar_maxProgress, 100)
|
||||||
|
currentProgress = typedArray.getInt(R.styleable.CircleProgressBar_currentProgress, 0)
|
||||||
|
startAngle = typedArray.getInt(R.styleable.CircleProgressBar_startAngle, -90).toFloat()
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
typedArray.recycle()
|
||||||
|
}
|
||||||
|
|
||||||
|
setupPaints()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupPaints() {
|
||||||
|
backgroundPaint.color = backgroundColor
|
||||||
|
backgroundPaint.strokeWidth = progressWidth
|
||||||
|
|
||||||
|
progressPaint.color = progressColor
|
||||||
|
progressPaint.strokeWidth = progressWidth
|
||||||
|
|
||||||
|
// 设置半透明效果,模仿图片中的绿色弧线
|
||||||
|
progressPaint.alpha = 180
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
val width = MeasureSpec.getSize(widthMeasureSpec)
|
||||||
|
val height = MeasureSpec.getSize(heightMeasureSpec)
|
||||||
|
viewSize = minOf(width, height)
|
||||||
|
setMeasuredDimension(viewSize, viewSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh)
|
||||||
|
|
||||||
|
val padding = progressWidth / 2
|
||||||
|
rectF.set(
|
||||||
|
padding,
|
||||||
|
padding,
|
||||||
|
w - padding,
|
||||||
|
h - padding
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
super.onDraw(canvas)
|
||||||
|
|
||||||
|
// 绘制背景圆环
|
||||||
|
canvas.drawArc(rectF, 0f, 360f, false, backgroundPaint)
|
||||||
|
|
||||||
|
// 绘制进度弧线
|
||||||
|
if (currentProgress > 0) {
|
||||||
|
val sweepAngle = (currentProgress.toFloat() / maxProgress) * 360f
|
||||||
|
canvas.drawArc(rectF, startAngle, sweepAngle, false, progressPaint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制中心图标
|
||||||
|
centerIcon?.let { icon ->
|
||||||
|
drawCenterIcon(canvas, icon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private fun drawCenterIcon(canvas: Canvas, icon: Bitmap) {
|
||||||
|
val centerX = width / 2f
|
||||||
|
val centerY = height / 2f
|
||||||
|
val iconWidth = icon.width.toFloat()
|
||||||
|
val iconHeight = icon.height.toFloat()
|
||||||
|
val iconBorderMargin = 12.dp
|
||||||
|
|
||||||
|
|
||||||
|
val scale: Float = if (iconWidth > iconHeight) {
|
||||||
|
(width - iconBorderMargin) / iconWidth
|
||||||
|
} else {
|
||||||
|
(height - iconBorderMargin) / iconHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
val scaledWidth = iconWidth * scale
|
||||||
|
val scaledHeight = iconHeight * scale
|
||||||
|
|
||||||
|
val left = centerX - scaledWidth / 2
|
||||||
|
val top = centerY - scaledHeight / 2
|
||||||
|
val right = centerX + scaledWidth / 2
|
||||||
|
val bottom = centerY + scaledHeight / 2
|
||||||
|
val dstRect = RectF(left, top, right, bottom)
|
||||||
|
|
||||||
|
canvas.drawBitmap(icon, null, dstRect, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setProgress(progress: Int) {
|
||||||
|
this.currentProgress = progress.coerceIn(0, maxProgress)
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCenterIcon(@DrawableRes iconRes: Int) {
|
||||||
|
centerIcon = BitmapFactory.decodeResource(resources, iconRes)
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setProgressColor(color: Int) {
|
||||||
|
progressColor = color
|
||||||
|
progressPaint.color = color
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getProgress(): Int = currentProgress
|
||||||
|
|
||||||
|
fun getMaxProgress(): Int = maxProgress
|
||||||
|
|
||||||
|
fun setMaxProgress(max: Int) {
|
||||||
|
maxProgress = max
|
||||||
|
if (currentProgress > maxProgress) {
|
||||||
|
currentProgress = maxProgress
|
||||||
|
}
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dpToPx(dp: Float): Float {
|
||||||
|
return dp * resources.displayMetrics.density
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
centerIcon?.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,5 +24,19 @@
|
||||||
<attr name="rightButtonSpacing" format="dimension"/>
|
<attr name="rightButtonSpacing" format="dimension"/>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="CircleProgressBar" tools:ignore="ResourceName">
|
||||||
|
<!-- 进度条颜色 -->
|
||||||
|
<attr name="progressColor" format="color|reference" />
|
||||||
|
<attr name="backgroundColor" format="color|reference" />
|
||||||
|
<attr name="progressWidth" format="dimension" />
|
||||||
|
|
||||||
|
<!-- 中间图标 -->
|
||||||
|
<attr name="centerIcon" format="reference" />
|
||||||
|
|
||||||
|
<!-- 进度相关 -->
|
||||||
|
<attr name="maxProgress" format="integer" />
|
||||||
|
<attr name="currentProgress" format="integer" />
|
||||||
|
<attr name="startAngle" format="integer" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -57,4 +57,8 @@
|
||||||
<color name="green_09">#ff00ff09</color>
|
<color name="green_09">#ff00ff09</color>
|
||||||
|
|
||||||
|
|
||||||
|
<color name="progress_green">#FF00FF5E</color>
|
||||||
|
<color name="progress_background">#99000000</color>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue