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

如何自定义Android Leanback组件VideoSupportFragment的进度条UI

Android TV VideoSupportFragment自定义播放UI方案

如果你需要完全替换VideoSupportFragment默认的playback row UI,实现自定义进度条、自定义操作按钮的播放界面,可按照以下步骤实现:

  • 移除默认playback row
    不需要单独移除操作按钮,直接禁用默认的播放控制组件即可。在自定义Fragment继承VideoSupportFragment后,在onViewCreated生命周期中隐藏默认控制栏,更高版本的Leanback库也可直接重写onCreatePlaybackControlsFragment方法返回null,完全不加载默认控制组件。
  • 注入自定义UI布局
    获取VideoSupportFragment生成的根布局(已包含视频渲染层),将自己提前写好的自定义播放控制布局(包含自定义进度条、操作按钮等)inflate到根布局中,可自行调整布局的位置、显示隐藏逻辑。
  • 绑定播放状态与交互
    通过PlaybackTransportControlGlue拿到播放控制器,监听播放状态、播放进度变化,同步更新自定义控件的显示;同时给自定义控件绑定点击/拖动事件,关联到播放器的播放、暂停、seek等操作即可。
  • 适配TV端特性
    给自定义控件设置focusable="true"、focusableInTouchMode="true",配置焦点选中样式,保证遥控器Dpad操作可以正常选中控件;重写按键事件回调,适配快进、快退、返回等TV端常用按键逻辑。

代码示例

public class CustomVideoPlayFragment extends VideoSupportFragment {
    private CustomSeekBar customSeekBar;
    private ImageButton playPauseBtn;
    private PlaybackTransportControlGlue<MediaPlayerAdapter> playbackGlue;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 获取父类自带视频渲染层的根视图
        View root = super.onCreateView(inflater, container, savedInstanceState);
        // 注入自定义控制布局
        View customControlView = inflater.inflate(R.layout.layout_custom_video_control, (ViewGroup) root, false);
        ((ViewGroup) root).addView(customControlView);
        // 初始化自定义控件
        customSeekBar = customControlView.findViewById(R.id.custom_seekbar);
        playPauseBtn = customControlView.findViewById(R.id.btn_play_pause);
        return root;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // 隐藏默认playback row
        if (getPlaybackControlsFragment() != null && getPlaybackControlsFragment().getView() != null) {
            getPlaybackControlsFragment().getView().setVisibility(View.GONE);
        }
        // 初始化播放控制器
        initPlaybackGlue();
        // 绑定自定义控件交互
        bindControlEvents();
    }

    private void initPlaybackGlue() {
        playbackGlue = new PlaybackTransportControlGlue<>(requireContext(), new MediaPlayerAdapter(requireContext()));
        playbackGlue.setHost(new VideoSupportFragmentGlueHost(this));
        // 监听播放状态变化更新UI
        playbackGlue.addCallback(new PlaybackGlue.PlayerCallback() {
            @Override
            public void onPlayStateChanged(PlaybackGlue glue) {
                playPauseBtn.setSelected(glue.isPlaying());
            }

            @Override
            public void onCurrentPositionChanged(PlaybackGlue glue, long position) {
                customSeekBar.setProgress((int) (position * 100 / glue.getDuration()));
            }
        });
        // 设置播放资源后调用playbackGlue.play()启动播放
    }

    private void bindControlEvents() {
        playPauseBtn.setOnClickListener(v -> {
            if (playbackGlue.isPlaying()) {
                playbackGlue.pause();
            } else {
                playbackGlue.play();
            }
        });
        customSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser) {
                    playbackGlue.seekTo(progress * playbackGlue.getDuration() / 100);
                }
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
    }
}

示例效果

示例图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 06:54:01