android录音的动画自定义View

引文

最近接了一下新需求,就像录音的按钮…

之前在微信小程序上也写过->小程序录音及其动画
去年在android上也实现过….下面是去年实现的时候的代码

大概这样
这里写图片描述

正文

首先View的绘制有几个过程,measure->layout->draw。如果本文的需求,高宽都是一定的,那么细节点就都在draw了。简单说有几个步骤:

  • onSizeChanged 初始化画笔,获取高宽等信息
  • onDraw 获取 canvas,进行绘制
  • postInvalidate() 数据有更新的时候触发重绘

canvas.draw 关注点主要是在纹理上,比如说圆形、方形,从哪个位置绘制到哪个位置
Paint.setShader 关注点在 色彩的渐变,颜色的遮罩

把之前android写过的代码放上来吧,也是一个笔记…

/*********************************************************************
 * This file is part of seeyoutime project
 * Created by [email protected] on 2017/2/21.
 * Copyright (c) 2017 XingDian Co.,Ltd. - All Rights Reserved
 *********************************************************************/

/**
 * 短视频录制界面的开始录制按钮,有如下特性:
 * 1,放大
 * 2,显示当前进度
 */
class ProgressRecordView : View {
    private var diameter = 0F
    private var barPressWidth = 0F
    private var barPressColor = 0xFFFFFFFF.toInt()
    private var bgPressColor = 0xFFFFFFFF.toInt()
    private var bgWidth = diameter

    private var bgInnerWidth = 0F
    private var bgInnerColor = 0xFFFFFFFF.toInt()
    private var bgColor = 0xFFFFFFFF.toInt()

    private val pressPaint = Paint()
    private val pressBgPaint = Paint()
    private val pressBarBounds = RectF()

    private val bgPaint = Paint()
    private val bgInnerPaint = Paint()

    val minProgress = 0
    val maxProgress = 360
    var pressing = false
    var progress = 0
        set(value) {
            field = value
            postInvalidate()
        }


    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
            super(context, attrs, defStyleAttr) {
        val array = context.obtainStyledAttributes(attrs, R.styleable.ProgressRecordView)
        //宽度都是指直径
        barPressWidth = array.getDimension(R.styleable.ProgressRecordView_barPressWidth, barPressWidth)
        bgInnerWidth = array.getDimension(R.styleable.ProgressRecordView_bgInnerWidth, bgInnerWidth)
        bgWidth = array.getDimension(R.styleable.ProgressRecordView_bgWidth, bgWidth)

        barPressColor = array.getColor(R.styleable.ProgressRecordView_barPressColor, barPressColor)
        bgPressColor = array.getColor(R.styleable.ProgressRecordView_bgPressColor, bgPressColor)
        bgInnerColor = array.getColor(R.styleable.ProgressRecordView_bgInnerColor, bgInnerColor)
        bgColor = array.getColor(R.styleable.ProgressRecordView_bgColor, bgColor)
        array.recycle()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec)
        //以宽度为准的正方形
    }

    override fun onSizeChanged(w: Int, h: Int, oldWidth: Int, oldHeight: Int) {
        super.onSizeChanged(w, h, oldWidth, oldHeight)
        diameter = w.toFloat()

        //set-up bounds
        pressBarBounds.set(barPressWidth / 2,
                barPressWidth / 2,
                width - barPressWidth / 2,
                height - barPressWidth / 2)

        //set-up paint
        pressPaint.color = barPressColor
        pressPaint.isAntiAlias = true
        pressPaint.style = Paint.Style.STROKE
        pressPaint.strokeWidth = barPressWidth

        pressBgPaint.color = bgPressColor
        pressBgPaint.isAntiAlias = true
        pressBgPaint.style = Paint.Style.FILL

        bgPaint.color = bgColor
        bgPaint.isAntiAlias = true
        bgPaint.style = Paint.Style.FILL

        bgInnerPaint.color = bgInnerColor
        bgInnerPaint.isAntiAlias = true
        bgInnerPaint.style = Paint.Style.FILL
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (pressing) {
            canvas?.drawCircle(diameter / 2, diameter / 2, diameter / 2 - 1, pressBgPaint)
            canvas?.drawArc(pressBarBounds, -90F, progress.toFloat(), false, pressPaint)
        } else {
            canvas?.drawCircle(diameter / 2, diameter / 2, bgWidth / 2, bgPaint)
            canvas?.drawCircle(diameter / 2, diameter / 2, bgInnerWidth / 2, bgInnerPaint)
        }
    }
}

values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    ...
    <declare-styleable name="ProgressRecordView">
        <attr name="barPressWidth" format="dimension" />
        <attr name="bgInnerWidth" format="dimension" />
        <attr name="bgWidth" format="dimension" />
        <attr name="barPressColor" format="color" />
        <attr name="bgPressColor" format="color" />
        <attr name="bgInnerColor" format="color" />
        <attr name="bgColor" format="color" />
    </declare-styleable>
</resources>

这样调用

<org.yeshen.seeyoutime.ProgressRecordView
    android:id="@+id/edit_video_record_btn"
    android:layout_width="120dp"
    android:layout_height="120dp"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="70dp"
    app:barPressColor="@color/yellow.light"
    app:barPressWidth="5dp"
    app:bgColor="@color/white"
    app:bgInnerColor="@color/yellow.light"
    app:bgInnerWidth="90dp"
    app:bgPressColor="@color/white"
    app:bgWidth="100dp" />
mRecordBtn.setOnClickListener {}
mRecordBtn.setOnTouchListener { _, event ->
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            mRecordBtnHint.visibility = View.INVISIBLE
            (mRecordBtn.tag as? ValueAnimator)?.cancel()
            mRecordBtn.tag = ObjectAnimator.ofInt(mRecordBtn.minProgress, mRecordBtn.maxProgress).apply {
                duration = VideoControlView.SHORT_VIDEO_LENGTH
                addUpdateListener { animation ->
                    mRecordBtn.pressing = true
                    mRecordBtn.progress = animation.animatedValue as Int
                }
                addListener(object : AnimatorListenerAdapter() {
                    override fun onAnimationEnd(animation: Animator) {
                        mRecordBtn.tag = null
                        mPlayerView?.stopRecord()
                    }
                })
                start()
            }
            mPlayerView?.record()
        }
        MotionEvent.ACTION_UP -> {
            (mRecordBtn.tag as? ValueAnimator)?.cancel()
        }
    }
    return@setOnTouchListener false
}


mRecordBtn.pressing = false
mRecordBtn.progress = 0

猜你喜欢

转载自blog.csdn.net/yeshennet/article/details/80652177