效果图
代码
- 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)
}
}
- 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>
资源图片