一个带小喇叭,带文本和背景进度条的控件

299 阅读2分钟

效果图

代码

  1. AudioPlayView.kt
package com.example.myapplication.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import com.example.myapplication.R
import com.example.myapplication.util.PxUtils
import java.util.*


/**
 * @Author:zhangchenzhou
 * @Date: 2019/9/16  10:18
 *@Description:
 */
class AudioPlayView(context: Context, attr:AttributeSet) :View(context,attr){
    var bgBitMap:Bitmap? = null
    var maskBitmap:Bitmap? = null
    var avAttr: AudioViewAttr = AudioViewAttr(context, attr)
    var bgPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    var textPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    var maskPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    var speakDotPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    var speakerPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    var textWidth = 0
    var textHeight = 0
    var dp13 = PxUtils.dpToPx(13,context).toFloat()
    private var progress:Int=0
    init {
        bgPaint.shader = LinearGradient(0f,avAttr.height/2.toFloat(),avAttr.width.toFloat(),avAttr.height/2.toFloat(),avAttr.bgStartColor,avAttr.bgEndColor, Shader.TileMode.CLAMP)
        textPaint.color=avAttr.textColor
        maskPaint.color=avAttr.maskColor
        speakDotPaint.color=avAttr.speakerColor
        speakerPaint.color=avAttr.speakerColor
        speakerPaint.style = Paint.Style.STROKE
        speakerPaint.strokeWidth = 6f
        speakerPaint.strokeCap = Paint.Cap.ROUND
        initTextWH()
    }
    fun initTextWH(){
        var rect = Rect()
        textPaint.textSize = avAttr.textSize.toFloat()
        textPaint.getTextBounds(avAttr.text,0,avAttr.text.length?:0,rect)
        textWidth = rect.width()
        textHeight = rect.height()
    }
    override fun onDraw(canvas: Canvas?) {
        if(bgBitMap==null){
            bgBitMap = scaleImage(BitmapFactory.decodeResource(resources,R.drawable.vip_intro),width,height)
        }
        if(bgBitMap!=null){
            canvas?.drawBitmap(bgBitMap!!,0f,0f,bgPaint)
        }
        if(maskBitmap!=null&&progress>0){
            canvas?.drawBitmap(maskBitmap!!,0f,0f,maskPaint)
        }
        canvas?.drawText(avAttr.text,PxUtils.dpToPx(26,context).toFloat(),(height+textHeight)/2.toFloat()-6,textPaint)
        drawSpeaker(canvas)
    }

    var rectf1:RectF? = null
    var rectf2:RectF? = null
    fun drawSpeaker(canvas: Canvas?){
        //用num对3取余的结果做判断
        var i = num%3
        canvas?.drawCircle(dp13,height/2.toFloat(),4.toFloat(),speakDotPaint)
        if(rectf1==null){
            rectf1=RectF(dp13-avAttr.speakerWAH/2,(height-avAttr.speakerWAH)/2.toFloat(),dp13+avAttr.speakerWAH/2,(height-avAttr.speakerWAH)/2.toFloat()+avAttr.speakerWAH)
        }
        if(rectf2==null){
            rectf2 = RectF(dp13-avAttr.speakerWAH,height/2-avAttr.speakerWAH.toFloat(),dp13+avAttr.speakerWAH,height/2+avAttr.speakerWAH.toFloat())
        }

        if(i==1){
            canvas?.drawArc(rectf1,315f,90f,false,speakerPaint)
        }
        if(i==2){
            canvas?.drawArc(rectf1,315f,90f,false,speakerPaint)
            canvas?.drawArc(rectf2,315f,90f,false,speakerPaint)
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(resolveSize(avAttr.width,measuredWidth), resolveSize(avAttr.height,measuredHeight))
    }

    /**
     * 按新的宽高缩放图片
     *
     * @param bm
     * @param newWidth
     * @param newHeight
     * @return
     */
    fun scaleImage(bm: Bitmap?, newWidth: Int, newHeight: Int): Bitmap? {
        var bm: Bitmap? = bm ?:
        return null
        val width = bm!!.width
        val height = bm.height
        val scaleWidth = newWidth.toFloat() / width
        val scaleHeight = newHeight.toFloat() / height
        val matrix = Matrix()
        matrix.postScale(scaleWidth, scaleHeight)
        val newbm = Bitmap.createBitmap(
            bm, 0, 0, width, height, matrix,
            true
        )
        if ((bm != null) and !bm.isRecycled) {
            bm.recycle()
            bm = null
        }
        return newbm
    }
    var timer:Timer? = null
    var num = 2
    fun startSpeakAnim(){
        if (timer!=null){
            timer?.cancel()
        }
        timer = Timer()
        timer?.schedule(object:TimerTask(){
            override fun run() {
                num++
                post {
                    invalidate()
                }
            }
        },800,800)
    }

    fun stopSpeakAnim(){
        num=2
        invalidate()
        timer?.cancel()
        timer=null
    }

    fun setProgress(progress:Int){
        this.progress = progress
        var tempWidth=(width*progress/100.0).toInt()
        if(tempWidth>width){
            tempWidth=width
        }
        if(tempWidth<=0){
            maskBitmap = null
        }else{
            maskBitmap = Bitmap.createBitmap(tempWidth,height,Bitmap.Config.ARGB_8888)
            Canvas(maskBitmap!!).drawColor(avAttr.maskColor)
        }
        invalidate()
    }
}
class AudioViewAttr(context: Context,attr: AttributeSet){
    var width:Int
    var height:Int
    var textColor:Int
    var bgStartColor:Int
    var bgEndColor:Int
    var maskColor:Int
    var text:String
    var textSize:Int
    var speakerWAH:Int
    var speakerColor:Int
    init {
        val ta = context.obtainStyledAttributes(attr, R.styleable.AudioIntroView)
        width = ta.getDimensionPixelSize(R.styleable.AudioIntroView_width,216)
        height = ta.getDimensionPixelSize(R.styleable.AudioIntroView_height,64)
        textColor = ta.getColor(R.styleable.AudioIntroView_introTextColor, Color.WHITE)
        bgStartColor = ta.getColor(R.styleable.AudioIntroView_bgStartColor,Color.GRAY)
        bgEndColor = ta.getColor(R.styleable.AudioIntroView_bgEndColor,Color.GRAY)
        maskColor = ta.getColor(R.styleable.AudioIntroView_maskColor,Color.GRAY)
        text = ta.getString(R.styleable.AudioIntroView_text)?:""
        textSize = ta.getDimensionPixelSize(R.styleable.AudioIntroView_introTextSize,27)
        speakerWAH = ta.getDimensionPixelSize(R.styleable.AudioIntroView_speakerWAH,30)
        speakerColor = ta.getColor(R.styleable.AudioIntroView_speakerColor,Color.WHITE)
    }
}
  1. attrs
<declare-styleable name="AudioIntroView">
        <attr name="width" format="dimension"/>
        <attr name="height" format="dimension"/>
        <attr name="bgStartColor" format="color"/>
        <attr name="bgEndColor" format="color"/>
        <attr name="introTextColor" format="color"/>
        <attr name="maskColor" format="color"/>
        <attr name="text" format="string"/>
        <attr name="introTextSize" format="dimension"/>
        <attr name="speakerWAH" format="dimension"/>
        <attr name="speakerColor" format="color"/>
    </declare-styleable>

资源图片