如果ImageView位置没有超出SeekBar的宽度,则计算坐标并移动,
如果它向外延伸,坐标将设置在ImageView的左侧或右侧。
※ExoPlayer使用ExoPlayer release-v2
java代码

public class ExoPlayerActivity extends FragmentActivity implements TextureView.SurfaceTextureListener {private ExoPlayerActivityBinding binding;private SimpleExoPlayer simpleExoPlayer;// Apple sample HLSprivate static final String videoUrl = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8";private Timer playerTimer;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = DataBindingUtil.setContentView(this, R.layout.exo_player_activity);// TextureView设置回调binding.textureView.setSurfaceTextureListener(this);// 隐藏状态栏和导航栏getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);View decor = getWindow().getDecorView();if (Build.VERSION.SDK_INT > 18) {decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);} else if (Build.VERSION.SDK_INT > 15) {decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);} else if (Build.VERSION.SDK_INT > 13) {decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);} else {decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);}// Player的比例按照16 : 9 设置binding.raitoFrameLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {if (binding.raitoFrameLayout.getWidth() > 0 && binding.raitoFrameLayout.getHeight() > 0) {int width = binding.raitoFrameLayout.getWidth();ViewGroup.LayoutParams params = binding.raitoFrameLayout.getLayoutParams();params.height = width / 16 * 9;binding.raitoFrameLayout.setLayoutParams(params);if (Build.VERSION.SDK_INT >= 16) {binding.raitoFrameLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);} else {binding.raitoFrameLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);}}}});// 显示Progressbarbinding.loadingProgress.setVisibility(View.VISIBLE);// SeekBar的事件监听binding.controlSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {if (progress == 0 || seekBar.getMax() == 0) return;if (fromUser) {// 用户手动调节Player进度条simpleExoPlayer.seekTo(progress * 1000);setThumbnailX(progress, seekBar.getMax());}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// 手动操作开始binding.loadingProgress.setVisibility(View.VISIBLE);}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// 手动操作结束binding.loadingProgress.setVisibility(View.INVISIBLE);}});}// 播放器监视器计时器更新秒数和SeekBar的位置private void setTimer() {stopTimer();playerTimer = new Timer();playerTimer.scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {final int durationSecond = (int) (simpleExoPlayer.getDuration() / 1000);final int currentSecond = (int) (simpleExoPlayer.getCurrentPosition() / 1000);binding.time.post(new Runnable() {@Overridepublic void run() {binding.time.setText(currentSecond + "/" + durationSecond);binding.controlSeek.setMax(durationSecond); // SeekBar的最大秒数设置binding.controlSeek.setProgress(currentSecond); // 将SeekBar的旋钮移动到当前秒数setThumbnailX(currentSecond, durationSecond);}});}}, 1000, 1000);}// 在SeekBar上移动图像的位置从View的大小计算位置private void setThumbnailX(int currentPosition, int durationPosition) {int seekWidth = binding.controlSeek.getWidth();int imageWidth = binding.videoImage.getWidth();double videoImageX = (double) seekWidth * currentPosition / durationPosition;if (videoImageX > seekWidth - imageWidth / 2) {binding.videoImage.setX(seekWidth - imageWidth);} else if (videoImageX > imageWidth / 2) {binding.videoImage.setX((int) videoImageX - imageWidth / 2);} else {binding.videoImage.setX(0);}}// Player监听Timer删除private void stopTimer() {if (playerTimer != null) {playerTimer.cancel();playerTimer.purge();playerTimer = null;}}@Overrideprotected void onResume() {super.onResume();if (simpleExoPlayer != null) {setTimer();simpleExoPlayer.setPlayWhenReady(true);}}@Overrideprotected void onPause() {super.onPause();stopTimer();if (simpleExoPlayer != null) {simpleExoPlayer.setPlayWhenReady(false);}}// ExoPlayer 2 TextureView设置为ExoPlayer,并在TextureView准备就绪时开始播放@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {Handler mainHandler = new Handler();BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);TrackSelector trackSelector = new DefaultTrackSelector(mainHandler, videoTrackSelectionFactory);LoadControl loadControl = new DefaultLoadControl();simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(getApplicationContext(), trackSelector, loadControl);simpleExoPlayer.setVideoTextureView(binding.textureView);DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,Util.getUserAgent(this, new WebView(getApplicationContext()).getSettings().getUserAgentString()), defaultBandwidthMeter);HlsMediaSource hlsMediaSource = new HlsMediaSource(Uri.parse(videoUrl), dataSourceFactory, mainHandler, null);simpleExoPlayer.prepare(hlsMediaSource);simpleExoPlayer.setVideoListener(new SimpleExoPlayer.VideoListener() {@Overridepublic void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {}@Overridepublic void onRenderedFirstFrame() {// 开始播放binding.loadingProgress.setVisibility(View.INVISIBLE);setTimer();}@Overridepublic void onVideoTracksDisabled() {}});simpleExoPlayer.setPlayWhenReady(true);}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}// ExoPlayer2
}
<layout><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#000"><RelativeLayout xmlns:tools="http://schemas.android.com/tools"android:id="@+id/raito_frame_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center"tools:context=".activity.ExoPlayerActivity"><TextureViewandroid:id="@+id/texture_view"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_margin="8dp"android:orientation="vertical"><TextViewandroid:id="@+id/time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="right|bottom"android:layout_margin="8dp"android:textColor="#FFF"android:textSize="16sp" /><ImageViewandroid:id="@+id/video_image"android:layout_width="64dp"android:layout_height="36dp"android:layout_margin="8dp"android:background="#FFF" /><SeekBarandroid:id="@+id/control_seek"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom" /></LinearLayout><ProgressBarandroid:id="@+id/loading_progress"style="?android:attr/progressBarStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true" /></RelativeLayout></FrameLayout>
</layout>

这样就可以实现在exoplayer中显示视频缩略图了。

ExoPlayer拖动进度条时显示视频缩略图相关推荐

  1. python 视频播放 拖动_视频画中画效果,拖动进度条可以seek到相应视频帧显示

    在视频开发中,我们常常看到这样的效果,拖动进度条时,或是在进度条上方或是在屏幕中间,显示拖动进度条位置时刻的某一帧画面. 这个需求,如果是你,你会如何做? 通常一个需求,不仅要考虑实现,还有考虑一些是 ...

  2. 异常:谷歌浏览器video标签播放视频不能拖动进度条

    谷歌浏览器video标签播放视频不能拖动进度条 当前端video的src不是直接使用视频文件的地址,而是通过后台下载接口返回文件流时,后台返回流因为没为response的header设置一些参数,会在 ...

  3. html如何设置视频不能拖动,video标签播放视频不能拖动进度条(示例代码)

    因为你的video的src不是直接使用视频文件的地址,而是通过后台接口返回文件流,后台返回流的时候没为response的header设置一些参数,否则会在部分浏览器有问题 String rangeSt ...

  4. 【Android FFMPEG 开发】FFMPEG 视频播放进度控制 ( 显示播放进度 | 拖动进度条播放 )

    文章目录 I . FFMPEG 播放进度控制 II . FFMPEG 播放视频 ( 效果展示 ) III . FFMPEG 获取视频时长 IV . FFMPEG 视频播放进度获取 V . FFMPEG ...

  5. 关于前端video标签视频无法拖动进度条快进问题(Django)

    因为后端返回的是视频的文件流,并不是视频文件地址.后端返回流的时候要为header设置一些参数,否则部分浏览器会出现问题(如Google Chrome...). django中常用返回文件流写法: c ...

  6. uniapp实现video视频禁止拖拽快进功能,禁止拖动进度条快进

    之前写了一篇文章 , 禁止快进的 , 但刚刚发现在uni-app中实现不了 , 所以又上网找别的方法,话不多说, 上代码 一 , template中 <video id="myVide ...

  7. 【网页上视频无法拖动进度条,如何进行加速播放操作以及网页失焦后如何可继续播放】

    面对网页视频无法加速时如何进行加速播放 遇到一 zhengzhi 刷题任务时 ,发现无法拖动进度条,也没有加速播放并且鼠标一失焦就会自动暂停时,让我乖乖看完是不可能,因此找了一个解决方案快速完成该任务 ...

  8. 微信小程序音频播放,可拖动进度条,可有时间显示

    首先来展示一下效果: 中间的播放条以及下面的浮窗就是我们呈现的最终效果. 音频播放使用的组件是: wx.getBackgroundAudioManager(); 在wx.request()中首先初始音 ...

  9. 微信小程序音频或视频拖动进度条时间不变解决方法

    问题描述: 微信小程序在较新版本的音频接口中推荐使用InnerAudioContext对象实现音频的播放.暂停.跳转等功能,通过监听接口回调实现. InnerAudioContext.onTimeUp ...

最新文章

  1. 电脑有独显内存还被占用_独显和集成显卡怎么分别
  2. 不知道什么期刊会议是国内计算机行业所承认的好会,顶会?中国计算机协会ccf了解一下!祝你圆梦顶刊、顶会
  3. VTK:可视化之Morph3D
  4. 【转载】快速、可伸缩和流式的AJAX代理--跨域持续内容分发
  5. ps怎么清屏_黑洞PS大赛刷屏!最后一张扎心了……
  6. linux下分割文件的方法,关于linux系统下分割大文件的方法
  7. 实验一 命令解释程序的编写
  8. 【转】RegSetValueEx运行时失败,返回代码为5,解决方法
  9. c/c++教程 - 2.4.1 类和对象,封装,class和struct的区别,成员属性设为私有,类拆分成.h.c文件编写方法
  10. 2022电工(技师)考试题库模拟考试平台操作
  11. Linux搭建可道云网盘
  12. 基于YOLO的新型RGB-D融合方法对行人进行检测和3D定位
  13. 网易BUFF产品体验报告
  14. GCT 英语单词全部核心词汇A-Z
  15. STL之容器——介绍
  16. 鸿蒙系统共享电脑文件,鸿蒙Hi3516通过NFS挂载方式与Windows共享文件
  17. 1688接口,item_search_seller - 搜索店铺列表
  18. blender测量3d模型的尺寸
  19. 生产者消费者3.0 阻塞队列版本
  20. matlab logpolar,GitHub - luxinjin/polar-code: matlab simulation for polar code

热门文章

  1. PIGOSS BSM对XenServer监控
  2. android 触摸屏驱动分析,rk3188--6.android 触摸屏驱动分析
  3. 微型计算机中储存器可分啊喂,01第一章微型计算机基础知识..ppt
  4. 【代码】Fluent Python
  5. 职场潜规则一、别威胁你的老板
  6. python文件处理,得到DNA的互补链或反向互补链
  7. 剑与远征服务器无限换,剑与远征兑换码2021年5月最新 剑与远征兑换码永久有效整理...
  8. 安卓平台airtest使用纪录
  9. AT指令(嵌入式+物联网)编程心得C语言
  10. Boost库-功能介绍-Geometry-R树-空间索引