Android开发视频预览效果

news/2024/10/11 7:51:14/
Android开发视频预览效果

视频播放不是一个简单的事情,得有暂停,继续播放等功能,屏幕的适配也是头疼的事情

一、思路:

引用的是腾讯播放器TXVodPlayer

二、效果图:

在这里插入图片描述图片不是很直观,也可以看下视频

Android开发教程实战案例源码分享-视频预览效果

三、关键代码:
public class ActiveVideoPreviewDialog extends AbsDialogFragment implements View.OnClickListener, ITXLivePlayListener {public static final String VIDEO_PATH = "videoPath";private TXCloudVideoView mTXCloudVideoView;private TXVodPlayer mPlayer;private String mVideoPath;private ObjectAnimator mPlayBtnAnimator;//暂停按钮的动画private View mPlayBtn;private boolean mPlayStarted;//播放是否开始了private boolean mPaused;//生命周期暂停private boolean mClickPaused;//点击暂停
//    private boolean mVideoFileFromRecord;private ActionListener mActionListener;@Overrideprotected int getLayoutId() {return R.layout.dialog_active_video_preview;}@Overrideprotected int getDialogStyle() {return R.style.dialog2;}@Overrideprotected boolean canCancel() {return true;}@Overrideprotected void setWindowAttributes(Window window) {WindowManager.LayoutParams params = window.getAttributes();params.width = WindowManager.LayoutParams.MATCH_PARENT;params.height = WindowManager.LayoutParams.MATCH_PARENT;window.setAttributes(params);}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);findViewById(R.id.btn_close).setOnClickListener(this);findViewById(R.id.video_container).setOnClickListener(this);mPlayBtn = findViewById(R.id.btn_play);//暂停按钮动画mPlayBtnAnimator = ObjectAnimator.ofPropertyValuesHolder(mPlayBtn,PropertyValuesHolder.ofFloat("scaleX", 4f, 0.8f, 1f),PropertyValuesHolder.ofFloat("scaleY", 4f, 0.8f, 1f),PropertyValuesHolder.ofFloat("alpha", 0f, 1f));mPlayBtnAnimator.setDuration(150);mPlayBtnAnimator.setInterpolator(new AccelerateInterpolator());mTXCloudVideoView = findViewById(R.id.video_view);mPlayer = new TXVodPlayer(mContext);mPlayer.setConfig(new TXVodPlayConfig());mPlayer.setPlayerView(mTXCloudVideoView);mPlayer.enableHardwareDecode(false);mPlayer.setRenderRotation(TXLiveConstants.RENDER_ROTATION_PORTRAIT);mPlayer.setRenderMode(TXLiveConstants.RENDER_MODE_FULL_FILL_SCREEN);mPlayer.setPlayListener(this);Bundle bundle = getArguments();if (bundle != null) {mVideoPath = bundle.getString(VIDEO_PATH);if (!TextUtils.isEmpty(mVideoPath)) {
//                mVideoFileFromRecord = mVideoPath.contains(CommonAppConfig.VIDEO_PATH_RECORD);int result = mPlayer.startPlay(mVideoPath);if (result == 0) {mPlayStarted = true;}}}}@Overridepublic void onPlayEvent(int e, Bundle bundle) {switch (e) {case TXLiveConstants.PLAY_EVT_PLAY_END://播放结束onReplay();break;case TXLiveConstants.PLAY_EVT_CHANGE_RESOLUTION://onVideoSizeChanged(bundle.getInt("EVT_PARAM1", 0), bundle.getInt("EVT_PARAM2", 0));onVideoSizeChanged();break;}}@Overridepublic void onNetStatus(Bundle bundle) {}/*** 获取到视频宽高回调*/public void onVideoSizeChanged() {double videoWidth = 0;double videoHeight = 0;MediaMetadataRetriever mmr = null;try {mmr = new MediaMetadataRetriever();mmr.setDataSource(mVideoPath);String width = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);//宽String height = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);//高String rotation = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);if ("0".equals(rotation)) {if (!TextUtils.isEmpty(width)) {videoWidth = Double.parseDouble(width);}if (!TextUtils.isEmpty(height)) {videoHeight = Double.parseDouble(height);}} else {if (!TextUtils.isEmpty(height)) {videoWidth = Double.parseDouble(height);}if (!TextUtils.isEmpty(width)) {videoHeight = Double.parseDouble(width);}}} catch (Exception e) {e.printStackTrace();} finally {if (mmr != null) {mmr.release();}}if (mTXCloudVideoView != null && videoWidth > 0 && videoHeight > 0) {FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mTXCloudVideoView.getLayoutParams();if (videoWidth / videoHeight > 0.5625f) {//横屏 9:16=0.5625params.height = (int) (mTXCloudVideoView.getWidth() / videoWidth * videoHeight);params.gravity = Gravity.CENTER;mTXCloudVideoView.requestLayout();}}}/*** 获取到视频宽高回调*/public void onVideoSizeChanged(float videoWidth, float videoHeight) {if (mTXCloudVideoView != null && videoWidth > 0 && videoHeight > 0) {FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mTXCloudVideoView.getLayoutParams();if (videoWidth / videoHeight > 0.5625f) {//横屏 9:16=0.5625params.height = (int) (mTXCloudVideoView.getWidth() / videoWidth * videoHeight);params.gravity = Gravity.CENTER;mTXCloudVideoView.requestLayout();}}}/*** 显示开始播放按钮*/private void showPlayBtn() {if (mPlayBtn != null && mPlayBtn.getVisibility() != View.VISIBLE) {mPlayBtn.setVisibility(View.VISIBLE);}}/*** 隐藏开始播放按钮*/private void hidePlayBtn() {if (mPlayBtn != null && mPlayBtn.getVisibility() == View.VISIBLE) {mPlayBtn.setVisibility(View.INVISIBLE);}}/*** 点击切换播放和暂停*/private void clickTogglePlay() {if (!mPlayStarted) {return;}if (mPlayer != null) {if (mClickPaused) {mPlayer.resume();} else {mPlayer.pause();}}mClickPaused = !mClickPaused;if (mClickPaused) {showPlayBtn();if (mPlayBtnAnimator != null) {mPlayBtnAnimator.start();}} else {hidePlayBtn();}}@Overridepublic void onPause() {super.onPause();mPaused = true;if (!mClickPaused && mPlayer != null) {mPlayer.pause();}}@Overridepublic void onResume() {super.onResume();if (mPaused) {if (!mClickPaused && mPlayer != null) {mPlayer.resume();}}mPaused = false;}/*** 循环播放*/private void onReplay() {if (mPlayStarted && mPlayer != null) {mPlayer.seek(0);mPlayer.resume();}}@Overridepublic void onClick(View v) {int i = v.getId();if (i == R.id.btn_close) {dismiss();} else if (i == R.id.video_container) {clickTogglePlay();}}@Overridepublic void onDestroy() {if (mPlayer != null) {mPlayer.stopPlay(false);mPlayer.setPlayListener(null);}mContext = null;mPlayer = null;mActionListener = null;super.onDestroy();}public void setActionListener(ActionListener actionListener) {mActionListener = actionListener;}public interface ActionListener {void onDeleteClick();}}
四、项目demo源码结构图:

在这里插入图片描述有问题或者需要完整源码的私信我


http://www.ppmy.cn/news/1537339.html

相关文章

旅游平台|智慧旅游平台|基于java的智慧旅游平台设计与实现(源码+数据库+文档)

智慧旅游平台 目录 基于java的智慧旅游平台设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布道师,阿里云开发…

Windows 编译 FFmpeg 源码详细教程

FFmpeg FFmpeg 是一个开源的多媒体框架,它包括了一整套工具和库,可以用来处理(转码、转换、录制、流式传输等)音频和视频。FFmpeg 支持广泛的音视频格式,并且可以在多种操作系统上运行,包括 Windows、Linux 和 macOS。 FFmpeg 的主要组件包括: ffmpeg:这是一个命令行工…

系统架构设计师-下午案例题(2018年下半年)

1.某文化产业集团委托软件公司开发一套文化用品商城系统,业务涉及文化用品销售、定制、竞拍和点评等板块,以提升商城的信息化建设水平。该软件公司组织项目组完成了需求调研,现已进入到系统架构设计阶段。考虑到系统需求对架构设计决策的影响,项目组先列出了可能影响系统架…

服装生产管理的数字化转型:SpringBoot框架

4 系统设计 4.1 系统结构设计 在结构设计过程中,首先对系统进行需求分析,然后进行系统初步设计,将系统功能模块细化,具体分析每一个功能模块具体应该首先哪些功能,最后将各个模块进行整合,实现系统结构的…

消费者Rebalance机制

优质博文:IT-BLOG-CN 一、消费者Rebalance机制 在Apache Kafka中,消费者组 Consumer Group会在以下几种情况下发生重新平衡Rebalance: 【1】消费者加入或离开消费者组: 当一个新的消费者加入消费者组或一个现有的消费者离开消费…

Wireshark数据包分析教程

Wireshark数据包分析教程 本教程将基于Wireshark工具捕获的数据包,逐步讲解网络数据帧中的各项信息,帮助你了解每个字段的含义及其作用。我们将从最基础的帧(Frame)信息开始,逐层解释包括以太网、IP、TCP、HTTP和JSON…

短视频矩阵系统独立源码/源头开发

短视频矩阵系统独立源码/源头开发 #抖音矩阵系统源码开发 #短视频矩阵系统源码开发 #短视频seo源码开发 一、 抖音短视频seo矩阵系统源码开发,需要掌握以下技术: 网络编程:能够使用Python、Java或其他编程语言进行网络编程,比如…

mac端口被占用解决方法

通常情况下:lsof -i:#{port} 就可以找到对应的进程的pid kill -9 #{pid} 直接终结 kill -15 #{pid} 等待正在进行的任务完成再终结 本次纪要 问题出现: 当我想要使用docker启动mysql的时候报错:Error response from daemon: Ports are not…