Android仿优酷视频的悬浮窗播放

之前接了需求要让视频播放时可以像优酷视频那样在悬浮窗里播放,并且悬浮窗和主播放页面之间要实现无缝切换,项目中使用的是自封装的ijkplayer
这个要求就代表不能在悬浮窗中新建视频控件,所以需要在悬浮窗中复用主页面的视频控件,以达到无缝衔接的效果。

主页面对应的视频控件的父view

 <FrameLayoutandroid:id="@+id/vw_live"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerInParent="true"/>

用FrameLayout作为添加视频控件的ParentView,通过addview方法将新建的播放器控件添加到父控件内部

vw_live = new IjkVideoView(this);
video_frame = findViewById(R.id.vw_live);
video_frame.addView(vw_live);

主播放界面的启动模式

播放主界面的activity的启动模式不能为默认,因为我们要保证播放主界面在显示悬浮窗的时候退到后台,但是整个的应用不能退到后台,所以activity的启动模式改为singleInstance

android:launchMode="singleInstance"

退到后台我们通过moveTaskToBack(true)方法;

moveTaskToBack(true);

可以让播放界面退到后台而整个应用不会退回后台

权限请求

要使用悬浮窗需要申请权限

<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
if (!Settings.canDrawOverlays(this)) {Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT);startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2);}

悬浮窗

 @SuppressLint("ClickableViewAccessibility")public void showFloatingWindowView(IjkVideoView view) {// 悬浮窗显示视图LayoutInflater layoutInflater = LayoutInflater.from(activity);mShowView = layoutInflater.inflate(R.layout.video_floating_window_layout, null);;// 获取系统窗口管理服务mWindowManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);// 悬浮窗口参数设置及返回mFloatParams = getParams();//floatingWindow内部控件实例init(view);// 设置窗口触摸移动事件mShowView.setOnTouchListener(new FloatViewMoveListener());// 悬浮窗生成mWindowManager.addView(mShowView, mFloatParams);}private void init(IjkVideoView viewGroup){videoLayout = mShowView.findViewById(R.id.floating_video);videoLayout.removeAllViews();if (viewGroup != null){ijkVideoView = viewGroup;videoLayout.addView(ijkVideoView,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));}mBtnCloseFloatingWindow = mShowView.findViewById(R.id.close_floating_view);mBtnCloseFloatingWindow.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {}});mBtnBackFloatingWindow = (ImageView)mShowView.findViewById(R.id.back_floating_view);mBtnBackFloatingWindow.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {}});}private WindowManager.LayoutParams getParams() {WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();//设置悬浮窗口类型if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;} else {layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;}//设置悬浮窗口属性layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;//设置悬浮窗口透明layoutParams.format = PixelFormat.TRANSLUCENT;//设置悬浮窗口长宽数据layoutParams.width = 500;layoutParams.height = 340;//设置悬浮窗显示位置layoutParams.gravity = Gravity.START | Gravity.TOP;layoutParams.x = 100;layoutParams.y = 100;return layoutParams;}

悬浮窗的xml,可通过自定义获得自己想要的效果

<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/floating_video_layout"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayoutandroid:id="@+id/floating_video"android:layout_width="match_parent"android:layout_height="match_parent"/><ImageViewandroid:id="@+id/close_floating_view"android:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="end"android:padding="10dp"android:src="@android:drawable/ic_menu_close_clear_cancel" /><ImageViewandroid:id="@+id/back_floating_view"android:layout_width="50dp"android:layout_height="50dp"android:padding="10dp"android:src="@android:drawable/ic_menu_revert" />
</FrameLayout>

悬浮窗的滑动,我们可以通过自定义点击监听实现

/*** 浮窗移动/点击监听*/private class FloatViewMoveListener implements View.OnTouchListener {//开始触控的坐标,移动时的坐标(相对于屏幕左上角的坐标)private int mTouchStartX;private int mTouchStartY;//开始时的坐标和结束时的坐标(相对于自身控件的坐标)private int mStartX, mStartY;//判断悬浮窗口是否移动,这里做个标记,防止移动后松手触发了点击事件private boolean isMove;@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {int action = motionEvent.getAction();int x = (int) motionEvent.getX();int y = (int) motionEvent.getY();switch (action) {case MotionEvent.ACTION_DOWN:isMove = false;mTouchStartX = (int) motionEvent.getRawX();mTouchStartY = (int) motionEvent.getRawY();mStartX = x;mStartY = y;break;case MotionEvent.ACTION_MOVE:int mTouchCurrentX = (int) motionEvent.getRawX();int mTouchCurrentY = (int) motionEvent.getRawY();mFloatParams.x += mTouchCurrentX - mTouchStartX;mFloatParams.y += mTouchCurrentY - mTouchStartY;mWindowManager.updateViewLayout(mShowView, mFloatParams);mTouchStartX = mTouchCurrentX;mTouchStartY = mTouchCurrentY;float deltaX = x - mStartX;float deltaY = y - mStartY;if (Math.abs(deltaX) >= 5 || Math.abs(deltaY) >= 5) {isMove = true;}break;case MotionEvent.ACTION_UP:break;default:break;}//如果是移动事件不触发OnClick事件,防止移动的时候一放手形成点击事件return isMove;}}

悬浮窗的消失,在这里调用videoLayout.removeAllViews()是为了将复用的视频控件的父View清空,返回主播放activity的时候调用addview方法不会再报 child view has Parent,you have to call removeView()的错

public void dismiss() {if (mWindowManager != null && mShowView != null) {videoLayout.removeAllViews();if (mShowView.getParent() != null){mWindowManager.removeView(mShowView);}}}

启动悬浮窗

 public videoFloatingWindow(Context context){super(context);this.activity = context;}

对于悬浮窗的调用

用hasBind来记录是否调用了悬浮窗

   private void startFloatingWindow(){if (!Settings.canDrawOverlays(this)) {Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT);startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2);} else {video_frame.removeView(vw_live);videoFloatingWindow.getInstance(this).showFloatingWindowView(vw_live);hasBind = true;moveTaskToBack(true);}}

注意

一.由于主界面activity使用了singleInstance启动模式,所以从悬浮窗返回主界面activity时,要添加flag

                Intent intent = new Intent(activity, activity.getClass());intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);activity.startActivity(intent);

二.当主界面的activity退回后台,再重新进入主界面的时候,注意,不再调用onCreate方法,而是调用onNewIntent,所以重写onNewIntent方法,重新进入主界面,悬浮窗消失

  @Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);Log.d("RemoteView", "重新显示了");//不显示悬浮框if (hasBind){videoFloatingWindow.getInstance(this).dismiss();video_frame.removeAllViews();if (vw_live != null){video_frame.addView(vw_live);}hasBind = false;}}

Android仿优酷视频的悬浮窗播放相关推荐

  1. android浮窗播放器,Android仿优酷视频的悬浮窗播放效果

    之前接了需求要让视频播放时可以像优酷视频那样在悬浮窗里播放,并且悬浮窗和主播放页面之间要实现无缝切换,项目中使用的是自封装的ijkplayer 这个要求就代表不能在悬浮窗中新建视频控件,所以需要在悬浮 ...

  2. android 优酷 自动全屏播放,Android如何实现仿优酷视频的悬浮窗播放效果

    Android如何实现仿优酷视频的悬浮窗播放效果 发布时间:2020-07-11 10:24:43 来源:亿速云 阅读:228 作者:清晨 这篇文章主要介绍Android如何实现仿优酷视频的悬浮窗播放 ...

  3. 仿优酷视频焦点轮播图布局html页面前端源码

    大家好,今天给大家介绍一款,仿优酷视频焦点轮播图布局html页面前端源码(图1).送给大家哦,获取方式在本文末尾. 图1 可以用菜单控制切换(图2) 图2 整体布局简洁明了,干净简单(图3) 图3 代 ...

  4. 优酷视频如何进行连续播放?

    优酷视频如何进行连续播放? 您可按下列方式打开和关掉持续播发: 移动端:开启优酷app-左上方[设定]-开启或关掉[持续播发]按键就可以. pc端:开启优酷pc客户端-点一下左上方[设定]-启用或不启 ...

  5. 优酷视频整段代理php,thinkphp仿优酷带数据源码|php仿优酷视频源码带后台功能强大...

    本项目是仿优酷官网,优酷官网是一个集多种知识面为一体的网站,能全面的锻炼我们的技能,所以我们决定仿优酷网. 本项目后台主要实现了:用户管理.分类管理.视频管理.评论管理.权限管理.轮播管理.网站配置和 ...

  6. android仿优酷菜单,Android编程实现仿优酷旋转菜单效果(附demo源码)

    本文实例讲述了Android编程实现仿优酷旋转菜单效果.分享给大家供大家参考,具体如下: 首先,看下效果: 不好意思,不会制作动态图片,只好上传静态的了,如果谁会,请教教我吧. 首先,看下xml文件: ...

  7. android电视 优酷视频,将优酷视频投屏到智能电视上,竟然还有这种操作

    原标题:将优酷视频投屏到智能电视上,竟然还有这种操作 现在很多人对投屏很感兴趣,通过一些软件或者工具可以将手机.电脑里的视频或者文件投放到智能电视上观看.今天小编也来尝试下,准备好一部安卓手机.一台智 ...

  8. android优酷视频黑屏,优酷视频打不开播放变黑屏的原因以及解决方法介绍

    今天打开优酷看视频,但是打开几个视频都打不开,只显示一个黑屏.我开始以为视频被删除了,但是看到有人还在评论,所以比较肯定的认为视频并没有删除,而是其他的原因所致. 优酷视频打不开 经验告诉我,这可能是 ...

  9. 怎样下载优酷视频到电脑上播放

    下载优酷视频上的视頻到电脑,有很多的方式,在其中有一种非常简单的,今日共享给大量的人了解. 01. 最先要进到优酷网 02. 在申请注册一个账户 03. 登录你申请注册的账户 04. 找到你喜爱的视頻 ...

最新文章

  1. 计算机网络:自顶向下方法(第七版)Wireshark实验指南
  2. 引用asp.net母版页后,母版页和内容页的页面事件执行顺序
  3. Generating RSA keys in PKCS#1 format in Java--转
  4. php 正则 回溯,php 正则表达式效率 贪婪、非贪婪与回溯分析
  5. Uoj 441 保卫王国
  6. 技术要求→物理安全→防盗窃和防破坏
  7. idea启动Tomcat控制台乱码但是不报错
  8. 电脑一开机内存(共8G)就用了70%以上,任务管理器里面查看没有占用内存很高的进程
  9. 概率分布-beta分布
  10. 腾讯视频外链获取,可以在微信、所有浏览器播放
  11. 新高考改革之下,有孚网络助力教育信息化进程
  12. 微信小程序地图图标controltap
  13. 合同管理模块样板html,可配置合同模板的合同管理系统的制作方法
  14. JDBC API 学习
  15. 【深度学习】深度学习入门:投身深度学习你需要哪些准备?
  16. Java程序百钱百鸡
  17. 5. 第五阶段 测试开发技术 - JAVA
  18. 机器学习算法[9]--集成方法之XGBoost原理详解及XGBoost库实现
  19. PQ(product quantization) 算法---(一)
  20. HOKUYO LIDAR URG-04 之 PYTHON驱动

热门文章

  1. Blender图解教程:新手入门练习1
  2. Duilib学习之仿酷狗开发(2)
  3. java养成类黄油_最近在家闲来无事,有没有什么养成类黄油?
  4. Android应用“今日事今日毕”发布了
  5. Mybatis-plus中Page参数
  6. 【Vue】模仿b站网站-----使用vue实现
  7. 做一名开源社区扫地僧(转)
  8. zookeeper客户端连接服务器的过程
  9. js实现echarts桑基图缩放与拖动
  10. 鹰谷靶点 | FDA批准首个乳腺癌CDK4/6抗耐药分子进入临床