如何为Android中的androidx.media3.ui.DefaultTimeBar设置圆角
解决DefaultTimeBar设置圆角的问题
你之前通过android:background设置圆角无效的原因是:DefaultTimeBar内部的已播放、缓冲、未播放区域是直接绘制在控件画布上的,会覆盖你设置的背景,因此看不到圆角效果。下面提供两种可行的解决方案:
方案一:自定义裁剪画布的DefaultTimeBar子类(推荐)
通过重绘时裁剪画布为圆角矩形,让所有进度内容都限制在圆角区域内,效果更统一。
- 创建自定义View类
import android.content.Context import android.graphics.Canvas import android.graphics.Path import android.graphics.RectF import android.util.AttributeSet import androidx.media3.ui.DefaultTimeBar class RoundedDefaultTimeBar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : DefaultTimeBar(context, attrs, defStyleAttr) { private var cornerRadius = 10f private val rect = RectF() private val path = Path() init { // 读取自定义属性中的圆角半径 val ta = context.obtainStyledAttributes(attrs, R.styleable.RoundedDefaultTimeBar) cornerRadius = ta.getDimension(R.styleable.RoundedDefaultTimeBar_cornerRadius, cornerRadius) ta.recycle() } override fun onDraw(canvas: Canvas) { // 裁剪画布为圆角矩形 rect.set(0f, 0f, width.toFloat(), height.toFloat()) path.reset() path.addRoundRect(rect, cornerRadius, cornerRadius, Path.Direction.CW) canvas.clipPath(path) super.onDraw(canvas) } }
- 添加自定义属性(在res/values/attrs.xml中)
如果没有attrs.xml文件,直接新建一个:
<resources> <declare-styleable name="RoundedDefaultTimeBar"> <attr name="cornerRadius" format="dimension" /> </declare-styleable> </resources>
- 替换布局中的DefaultTimeBar
把原布局里的androidx.media3.ui.DefaultTimeBar替换为自定义View(注意替换为你的包名):
<com.your.package.name.RoundedDefaultTimeBar android:id="@+id/exo_progress" android:layout_width="0dp" android:layout_height="@dimen/dimen_12dp" android:layout_gravity="center" android:layout_marginTop="@dimen/dimen_2dp" android:layout_marginLeft="@dimen/dimen_30dp" app:layout_constraintTop_toBottomOf="@id/window_close" app:layout_constraintLeft_toRightOf="@id/exo_player_fwd_ten_sec" app:layout_constraintRight_toLeftOf="@id/exo_playback_speed" app:buffered_color="@android:color/white" app:played_color="@android:color/black" app:scrubber_color="@android:color/black" app:unplayed_color="@android:color/white" app:cornerRadius="10dp" app:scrubber_drawable="@drawable/thumb" android:visibility="visible"/>
方案二:替换内置进度Drawable
通过为已播放、缓冲、未播放区域分别设置带圆角的Shape Drawable,实现圆角效果。
- 创建三个带圆角的Shape Drawable
- 未播放区域:
res/drawable/exo_time_bar_unplayed_rounded.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="10dp" /> <solid android:color="@android:color/white" /> </shape>
- 缓冲区域:
res/drawable/exo_time_bar_buffered_rounded.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="10dp" /> <solid android:color="@android:color/white" /> </shape>
- 已播放区域:
res/drawable/exo_time_bar_played_rounded.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="10dp" /> <solid android:color="@android:color/black" /> </shape>
- 在代码中为DefaultTimeBar设置Drawable
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.media3.ui.DefaultTimeBar class YourActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.your_layout) val timeBar = findViewById<DefaultTimeBar>(R.id.exo_progress) timeBar.setUnplayedDrawable(ContextCompat.getDrawable(this, R.drawable.exo_time_bar_unplayed_rounded)) timeBar.setBufferedDrawable(ContextCompat.getDrawable(this, R.drawable.exo_time_bar_buffered_rounded)) timeBar.setPlayedDrawable(ContextCompat.getDrawable(this, R.drawable.exo_time_bar_played_rounded)) } }
两种方案对比
- 方案一:通过画布裁剪实现,整个进度条的所有内容都被限制在圆角内,效果统一,适合需要整体圆角的场景。
- 方案二:每个进度层都是独立的圆角Shape,当播放进度不满时,已播放层的右端也会显示圆角,适合需要进度层单独圆角的场景。
内容的提问来源于stack exchange,提问作者Gyan Swaroop Awasthi
相关产品推荐
相关产品推荐

