You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android音频录制播放动画实现:Telegram已播放区域填充方案问询

Android实现Telegram风格音频播放进度填充效果

嘿,关于你想做的这种音频录制/播放视图的已播放部分填充效果(就像Telegram那样,初始灰色,播放过的区域变蓝色),我刚好有几个实用的方案可以分享给你,而且比你最初设想的两张图+FrameLayout要更灵活可控哦~

方案一:用LayerDrawable + ClipDrawable快速实现(无需自定义View)

这个方案适合快速落地,不用写自定义View的代码,完全靠Drawable配置就能搞定:

  1. 准备基础Drawable资源

    • 先做一个灰色的未播放背景(带圆角,贴合Telegram的风格),比如res/drawable/audio_bg_gray.xml:
      <?xml version="1.0" encoding="utf-8"?>
      <shape xmlns:android="http://schemas.android.com/apk/res/android"
          android:shape="rectangle">
          <solid android:color="#E0E0E0"/>
          <corners android:radius="16dp"/>
      </shape>
      
    • 再做一个蓝色的已播放前景,res/drawable/audio_bg_blue.xml:
      <?xml version="1.0" encoding="utf-8"?>
      <shape xmlns:android="http://schemas.android.com/apk/res/android"
          android:shape="rectangle">
          <solid android:color="#2196F3"/>
          <corners android:radius="16dp"/>
      </shape>
      
  2. 创建LayerDrawable组合+ClipDrawable控制显示
    新建res/drawable/audio_progress_drawable.xml,把蓝色前景用ClipDrawable包裹,放在灰色背景上层:

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- 底层:灰色未播放背景 -->
        <item android:drawable="@drawable/audio_bg_gray"/>
        <!-- 上层:蓝色已播放部分,用ClipDrawable控制显示比例 -->
        <item>
            <clip
                android:drawable="@drawable/audio_bg_blue"
                android:clipOrientation="horizontal"
                android:gravity="left"/>
        </item>
    </layer-list>
    
  3. 在布局和代码中使用
    布局里用ImageView加载这个drawable:

    <ImageView
        android:id="@+id/audio_progress_view"
        android:layout_width="match_parent"
        android:layout_height="32dp"
        android:background="@drawable/audio_progress_drawable"/>
    

    代码里获取ClipDrawable,通过设置level来更新播放进度(level范围是0-10000,对应0%-100%):

    val progressView = findViewById<ImageView>(R.id.audio_progress_view)
    val clipDrawable = (progressView.background as LayerDrawable).getDrawable(1) as ClipDrawable
    
    // 比如播放到30%,设置level为3000
    clipDrawable.level = (progress * 10000).toInt()
    

方案二:自定义View(更灵活,适合复杂需求)

如果需要更个性化的效果(比如渐变填充、动态波形、圆角细节调整),自定义View是更好的选择:

class AudioProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val bgPaint = Paint().apply {
        color = Color.parseColor("#E0E0E0")
        isAntiAlias = true
        style = Paint.Style.FILL
    }

    private val progressPaint = Paint().apply {
        color = Color.parseColor("#2196F3")
        isAntiAlias = true
        style = Paint.Style.FILL
    }

    private var progress = 0f // 0-1的进度值
    private val radius = 16.dpToPx(context).toFloat()

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 绘制灰色背景
        canvas.drawRoundRect(0f, 0f, width.toFloat(), height.toFloat(), radius, radius, bgPaint)
        // 绘制蓝色进度部分
        val progressWidth = width * progress
        canvas.drawRoundRect(0f, 0f, progressWidth, height.toFloat(), radius, radius, progressPaint)
    }

    fun setProgress(progress: Float) {
        this.progress = progress.coerceIn(0f, 1f) // 限制在0-1之间
        invalidate() // 触发重绘
    }

    private fun Int.dpToPx(context: Context): Int {
        return (this * context.resources.displayMetrics.density).toInt()
    }
}

然后在布局里直接使用:

<com.yourpackage.AudioProgressView
    android:id="@+id/custom_audio_progress"
    android:layout_width="match_parent"
    android:layout_height="32dp"/>

代码里更新进度就调用custom_audio_progress.setProgress(0.3f)就行。

关于你最初的FrameLayout思路

其实用FrameLayout叠加两个View也能实现:灰色View当背景,蓝色View放在上面,通过设置蓝色View的layout_width或者scaleX来控制显示宽度。但这种方式在处理圆角时容易出现边缘错位,而且频繁更新宽度可能不如前两种方案高效,所以更推荐上面的两种方法哦~

内容的提问来源于stack exchange,提问作者Maksim Dmitriev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:31:50