如何自定义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
相关产品推荐
相关产品推荐

