学习|Android中实现进度条按钮功能(kotlin)

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为1029,预计阅读4分钟


Android中实现按钮进度条

前面几章做了检测TTS及怎么样进度条下载的文章,原想结合几个知识点做一个实战操作,模仿应用宝等手机助手的那种列表下载方式,计划中发现有一环是需要实现个一按钮进度条的方式,看了看以前没有相关的东西,那这篇我们就在看看Android怎么实现按钮进度条的功能。

实现效果

实现思路

要实现ProgressBar加上Button的方式,我们需要自定义类继承自View 

然后在进度条滚动的时候进行样式布局的重画

创建xml的自定义属性和点击的接口监听事件

实现按钮进度条,并重新按钮的事件

划重点

我这里实现的是一个简单的方式,可以在这个基础上加上自己的一些新的设计,比如说加载进度条时的颜色和背景色重设,按钮在不同状态下的不同颜色,进度条中状态的监听等方法实现。

代码演示

微卡智享

ProgressButton

package dem.vac.progressbutton


import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View


class ProgressButton : View {

    constructor(context: Context?, attrs: AttributeSet?) : super( context, attrs){
        init(context!!, attrs!!)
    }


    constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs){
        init(context!!, attrs!!)
    }


    private lateinit var fm: Paint.FontMetrics
    private var progress = 0
    private var textColor: Int = Color.WHITE
    private var paint: Paint? = null
    private var textSize: Float = 10f
    private var foreground = 0
    private var backgroundcolor = 0
    private var text: String? = null
    private var max = 100
    private val corner = 5 // 圆角的弧度
    private var buttonClickListener: OnProgressButtonClickListener? = null


    private fun init(
        context: Context,
        attrs: AttributeSet
    ) {
        val typedArray =
            context.obtainStyledAttributes(attrs, R.styleable.ProgressButton)
        backgroundcolor = typedArray.getInteger(
            R.styleable.ProgressButton_backgroundcolor,
            Color.parseColor("#C6C6C6")
        )
        foreground = typedArray.getInteger(
            R.styleable.ProgressButton_foreground,
            Color.rgb(20, 131, 214)
        )
        textColor = typedArray.getInteger(
            R.styleable.ProgressButton_textcolor,
            Color.WHITE
        )
        max = typedArray.getInteger(R.styleable.ProgressButton_max, 100)
        progress = typedArray.getInteger(R.styleable.ProgressButton_progress, 0)
        text = typedArray.getString(R.styleable.ProgressButton_text)
        textSize = typedArray.getDimension(R.styleable.ProgressButton_textSize, 20f)
        typedArray.recycle()
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        paint = Paint()
        paint!!.setAntiAlias(true)
        paint!!.setStrokeWidth(5f)
        /**
         * 绘制背景
         */
        var oval = RectF(0F, 0F, width.toFloat(), height.toFloat())
        paint!!.setColor(this.backgroundcolor)
        canvas.drawRoundRect(oval, corner.toFloat(), corner.toFloat(), paint)
        /***
         * 绘制进度值
         */
        paint!!.setColor(foreground)
        if (progress <= corner) {
            oval = RectF(
                0F,
                (corner - progress).toFloat(),
                (width * progress / max).toFloat(),
                (height
                        - corner + progress).toFloat()
            )
            canvas.drawRoundRect(oval, progress.toFloat(), progress.toFloat(), paint)
        } else {
            oval = RectF(
                0F, 0F,
                (width * progress / max).toFloat(),
                height.toFloat()
            )
            canvas.drawRoundRect(oval, corner.toFloat(), corner.toFloat(), paint)
        }
        /***
         * 绘制文本
         */
        if ("" == text || text == null) {
            return
        }
        paint!!.setTextSize(textSize)
        fm = paint!!.getFontMetrics()
        paint!!.setColor(textColor)
        val textCenterVerticalBaselineY =
            height / 2 - fm.descent + (fm.descent - fm.ascent) / 2
        canvas.drawText(
            text,
            (measuredWidth - paint!!.measureText(text)) / 2,
            textCenterVerticalBaselineY,
            paint
        )
    }

    /**
     * 设置最大值
     *
     * @param max
     */
    fun setMax(max: Int) {
        this.max = max
    }

    /**
     * 设置文本提示信息
     *
     * @param text
     */
    fun setText(text: String?) {
        this.text = text
    }

    /**
     * 设置进度条的颜色值
     *
     * @param color
     */
    fun setForeground(color: Int) {
        foreground = color
    }

    /**
     * 设置进度条的背景色
     */
    override fun setBackgroundColor(color: Int) {
        this.backgroundcolor = color
    }

    /***
     * 设置文本的大小
     */
    fun setTextSize(size: Int) {
        textSize = size.toFloat()
    }

    /**
     * 设置文本的颜色值
     *
     * @param color
     */
    fun setTextColor(color: Int) {
        textColor = color
    }

    /**
     * 设置进度值
     *
     * @param progress
     */
    fun setProgress(progress: Int) {
        if (progress > max) {
            return
        }
        this.progress = progress
        //设置进度之后,要求UI强制进行重绘
        postInvalidate()
    }

    fun getMax(): Int {
        return max
    }

    fun getProgress(): Int {
        return progress
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_UP -> buttonClickListener!!.onClickListener()
            else -> {
            }
        }
        return true
    }

    fun setOnProgressButtonClickListener(clickListener: OnProgressButtonClickListener) {
        buttonClickListener = clickListener
    }


    interface OnProgressButtonClickListener {
        fun onClickListener()
    }

}

自定义属性attr

我们在Android的res--values下面创建一个attr.xml,名称起什么倒是无所谓

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ProgressButton">  
        <attr name="backgroundcolor" format="color"  /> 
        <attr name="foreground" />  
        <attr name="textcolor" format="color" />  
        <attr name="max" />  
        <attr name="progress" />  
        <attr name="textSize" />  
        <attr name="text" format="string" />
    </declare-styleable>
</resources>

通过上面两步,我们的ProgressButton的自定义控件就实现了,接下来我们就看看怎么去使用。

ProgressButton使用

微卡智享

activity_main.xml

在主窗体的布局文件中可以直接就加入我们刚才已经生成的ProgressButton

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <dem.vac.progressbutton.ProgressButton
        android:layout_gravity="center"
        android:layout_width="100dp"
        android:layout_height="50dp"
        app:backgroundcolor="@color/colorLightSkyBlue"
        app:foreground="@color/colorRoyalBlue"
        app:textcolor="@color/colorWhite"
        app:text="点击开始"
        android:id="@+id/progressbtn" />

</LinearLayout>

MainActivity.kt

接下来看看我们主程序的使用代码

package dem.vac.progressbutton

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlin.concurrent.thread

class MainActivity : AppCompatActivity() {

    lateinit var probtn: ProgressButton

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        probtn = findViewById(R.id.progressbtn)
        probtn.setOnProgressButtonClickListener(object :
            ProgressButton.OnProgressButtonClickListener {
            override fun onClickListener() {
                thread {
                    for (i in 1..100) {
                        probtn.setProgress(i)
                        probtn.setText("当前$i")
                        Thread.sleep(50)
                    }
                }
            }
        })
    }

}

代码中我们直接就调用到ProgressButton,然后重写了onProgressButtonClickListerner事件,事件中我们开启了一个线程,做了一1到100的循环,调用到的效果就是我们文章开头的那个动图效果。

扫描二维码

获取更多精彩

微卡智享

「 往期文章 」

学习|Android检测并自动下载安装包(Kotlin)

学习|Android使用TTS语音合成

实战|Android文字滚动自定义动画

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值