欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

android录音的动画自定义View

程序员文章站 2022-04-25 17:41:09
...
引文

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

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

大概这样
android录音的动画自定义View

正文

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

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

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

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

/*********************************************************************
 * This file is part of seeyoutime project
 * Created by aaa@qq.com 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()
        }
    }
    aaa@qq.com false
}


mRecordBtn.pressing = false
mRecordBtn.progress = 0
相关标签: processview record