使用kotlin实现一个简单的Android圆形ProgressBar

本自定义View功能比较简单,就是一个包含百分比的圆形进度条,先上结果图(新手,大神勿喷)

代码如下所示,支持padding设置,背景线条颜色设置


<?xml version="1.0" encoding="utf-8"?>    "CircleProgressBar">        "backgroundColor" format="color" />        "textColor" format="color" />        "arcWidth" format="integer" />    //CircleProgressBar.ktpackage com.hefuwei.progressviewimport android.content.Contextimport android.graphics.Canvasimport android.graphics.Colorimport android.graphics.Paintimport android.graphics.Rectimport android.os.Buildimport android.support.annotation.RequiresApiimport android.util.AttributeSetimport android.view.View/** * Created by hefuwei on 2018/3/29. */class CircleProgressBar(context:Context,set:AttributeSet?): View(context,set){    private val paint:Paint = Paint(Paint.ANTI_ALIAS_FLAG) //设置抗锯齿    private val smallestSize:Int = 150 //当设置为wrap_content时的最小尺寸    private var progress:Int = 0     private val arcWidth:Int //进度条外边缘线    private val boundRect = Rect()    init {        val typeArray = context.obtainStyledAttributes(set,R.styleable.CircleProgressBar)        setBackgroundColor(typeArray.getColor(R.styleable.CircleProgressBar_backgroundColor,Color.BLACK)) //获取xml定义的backgroundColor并设置        paint.color = typeArray.getColor(R.styleable.CircleProgressBar_textColor,Color.WHITE)        arcWidth = typeArray.getInt(R.styleable.CircleProgressBar_arcWidth,3)        paint.strokeWidth = arcWidth.toFloat()        typeArray.recycle() //回收typeArray 防止内存泄露    }    constructor(context: Context):this(context, null) //次构造器    @RequiresApi(Build.VERSION_CODES.LOLLIPOP) //偷个懒不用RectF    override fun onDraw(canvas: Canvas?) {        super.onDraw(canvas)        val width = measuredWidth - paddingLeft - paddingRight //获取实际可用于绘制的宽高        val height = measuredHeight - paddingBottom - paddingTop         if(canvas != null){            paint.style = Paint.Style.FILL //使用填充模式画文字            if(progress >= 10){                drawText("$progress%",canvas)            }else{                drawText("0$progress%",canvas)            }            paint.color = Color.RED            paint.style = Paint.Style.STROKE //使用画线模式画圆弧            if(height > width){ //计算圆弧位置 以最小边的一半为半径                canvas.drawArc(paddingLeft.toFloat()+arcWidth/2,                          (height-width+arcWidth)/2.toFloat(),                        measuredWidth.toFloat()-arcWidth/2-paddingRight,                        (height+width+arcWidth)/2.toFloat(),                        135f,2.7f*progress.toFloat(),false,paint)            } else {                canvas.drawArc((width-height)/2.toFloat(),                        paddingTop.toFloat()+arcWidth/2,                        (width+height)/2.toFloat(),                        measuredHeight.toFloat()-arcWidth/2-paddingBottom,                        135f,2.7f*progress.toFloat(),false,paint)            }        }    }    private fun drawText(str:String, canvas:Canvas){        paint.getTextBounds(str,0,str.length,boundRect) //注意drawText的起点是位于第一个字的左下        canvas.drawText(str,(measuredWidth-boundRect.right+boundRect.left+paddingLeft-paddingRight)/2.toFloat()                ,(measuredHeight+boundRect.bottom-boundRect.top-paddingTop-paddingBottom)/2.toFloat(),paint)    }    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec)        val widthSize = MeasureSpec.getSize(widthMeasureSpec)        val widthMode = MeasureSpec.getMode(widthMeasureSpec)        val heightSize = MeasureSpec.getSize(heightMeasureSpec)        val heightMode = MeasureSpec.getMode(heightMeasureSpec)        if(widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){ //解决wrap_content与match_content效果一致的问题            setMeasuredDimension(smallestSize,smallestSize)        }else if(widthMode == MeasureSpec.AT_MOST){            setMeasuredDimension(smallestSize,heightSize)        }else if(heightMode == MeasureSpec.AT_MOST){            setMeasuredDimension(widthSize,smallestSize)        }        chooseRightTextSize() //选择合适的textSize避免text比外面的框大    }    private fun chooseRightTextSize(){        var lastSize = 1        for(i in 1..500){            paint.textSize = i.toFloat()            paint.getTextBounds("100%",0,"100%".length,boundRect)            if((boundRect.right - boundRect.left)*1.9 < measuredWidth-paddingLeft-paddingRight &&                    (boundRect.bottom - boundRect.top)*4 < measuredHeight-paddingTop-paddingBottom){                lastSize = i            }else{                paint.textSize = lastSize.toFloat()                return            }        }    }    fun setProgress(progress:Int){          when {            progress < 0 -> this.progress = 0            progress > 100 -> this.progress = 100            else -> this.progress = progress        }        invalidate() //调用该方法后立即刷新视图    }    fun getProgress():Int = progress}//根据自己喜爱给progressBar设置背景,线条粗细<?xml version="1.0" encoding="utf-8"?>"http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.hefuwei.progressview.MainActivity">    <com.hefuwei.progressview.CircleProgressBar        android:id="@+id/cb"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_centerInParent="true"        app:arcWidth="40"           app:backgroundColor="#fff"        app:textColor="#000" />
  • 最后在MainActivity里面使用属性动画即可出现本文开头的动画
//MainActivity.ktpackage com.hefuwei.progressviewimport android.animation.ObjectAnimatorimport android.support.v7.app.AppCompatActivityimport android.os.Bundleimport kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        val animator = ObjectAnimator.ofInt(cb,"progress",100)        animator.duration = 10000        animator.start()    }}

最后附上github地址

更多相关文章

  1. android photoview 图片放大缩放功能 ImageView
  2. android:configChanges属性
  3. 设置TextView文字居中
  4. 使用迅雷代替SDK Manager快速下载Android(安卓)SDK相关
  5. 在Windows系统中使用NDK编译Android二进制文件并运行
  6. 安卓第三天---ViewPager控件实现滑动切换图片
  7. Android笔记-3
  8. Android使用Intent调用摄像头并获取照片
  9. android警告——Buttons in button bars should be border

随机推荐

  1. unity发布android流程
  2. 如何运用百度地图SDK进行开发(一)初级篇
  3. Android AsyncTask 初探
  4. Android(安卓)通过DownloadManager实现自
  5. Android五个进程等级
  6. 【android】初学安卓,简单布局和activity
  7. Android的animation(动画)
  8. 弄错一个概念:Android的Thread与Handler是
  9. Android(安卓)ArrayList LinkedList Set
  10. 分享第一本中文Android书籍(应用框架和程