之前接了需求要让视频播放时可以像优酷视频那样在悬浮窗里播放,并且悬浮窗和主播放页面之间要实现无缝切换,项目中使用的是自封装的ijkplayer

这个要求就代表不能在悬浮窗中新建视频控件,所以需要在悬浮窗中复用主页面的视频控件,以达到无缝衔接的效果。

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

android: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);

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

权限请求

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

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() {

@Override

public void onClick(View v) {

}

});

mBtnBackFloatingWindow = (ImageView)mShowView.findViewById(R.id.back_floating_view);

mBtnBackFloatingWindow.setOnClickListener(new View.OnClickListener() {

@Override

public 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,可通过自定义获得自己想要的效果

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/floating_video_layout"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/floating_video"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

android: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" />

android:id="@+id/back_floating_view"

android:layout_width="50dp"

android:layout_height="50dp"

android:padding="10dp"

android:src="@android:drawable/ic_menu_revert" />

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

/**

* 浮窗移动/点击监听

*/

private class FloatViewMoveListener implements View.OnTouchListener {

//开始触控的坐标,移动时的坐标(相对于屏幕左上角的坐标)

private int mTouchStartX;

private int mTouchStartY;

//开始时的坐标和结束时的坐标(相对于自身控件的坐标)

private int mStartX, mStartY;

//判断悬浮窗口是否移动,这里做个标记,防止移动后松手触发了点击事件

private boolean isMove;

@Override

public 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方法,重新进入主界面,悬浮窗消失

@Override

protected 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仿优酷视频的悬浮窗播放的文章就介绍到这了,更多相关android 优酷视频悬浮窗播放内容请搜索云海天教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持云海天教程!

原文链接:https://blog.csdn.net/why931022/article/details/107229849

android浮窗播放器,Android仿优酷视频的悬浮窗播放效果相关推荐

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

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

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

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

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

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

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

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

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

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

  6. 优酷在线播放器 html5,看优酷,用HTML5

    大家都说Safari好用,我也觉得挺好用的:大家都说ClickToPluginForChina很好用,可是我却死活用不起来.虽然2020年底Adobe将停止支持Flash,但是在此之前的日子还是要过. ...

  7. php 手机swf播放器,php获取优酷土豆页面中视频swf播放器地址_PHP教程

    项目用到临时写的.待完善 /* * 根据用户提交的(swf/html)地址,获取优酷,土豆的swf播放地址 * */ private function _getSwf ($url = ") ...

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

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

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

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

最新文章

  1. 事件相机角点检测,从原理到demo
  2. WIFI搜索的到别人,却找不到自己家的wifi
  3. tpcc-mysql的使用
  4. cad版本在线转换_一套某中学的弱电系统拓扑设计方案(CAD版本)
  5. Authentication和Authorization的区别
  6. java之DocumentBuilderFactory解析xml
  7. java多态+多态中隐含的问题
  8. Hadoop安装之JDK在Centos虚拟机中安装
  9. linux安半程序自动确认,利用system-config-kickstart实现半自动化安装
  10. 【数据结构】堆、堆排序笔记
  11. 2008 iis php mysql_2008服务器配置iis7+php+mysql
  12. 车联网的麻烦和便利一样多 BAT们要治这种尴尬症
  13. 手机连上蓝牙耳机没有声音
  14. 怎么把台式电脑的大量数据快速迁移到笔记本
  15. [Power Query]:自动提取自定义一周的数据
  16. android微信7,微信7.0安卓版之初体验
  17. 【Android Studio】Android Studio 搭建开发环境(Linux Ubuntu篇)
  18. 多核处理器的运行模式
  19. 网页设计作业 开心网旅游(11页) web前端期末大作业 html+css+javascript网页设计实例
  20. 华为OD机试(C语言)真题

热门文章

  1. 一文搞懂SQL-计算众数、中位数
  2. mysql查询中位数(窗口函数的使用)
  3. 一键去除开发者模式提示
  4. NCC低代码平台走过的坑(持续更新)
  5. vue 移动端 触摸事件
  6. 每天一万步,一周减十斤
  7. python怎么加字幕_Python如何实现字幕挂载 Python实现字幕挂载代码示例
  8. 载着人类梦想的猎户座宇宙飞船 设计居然是通过AR来实现的!
  9. 51 使用ThreeBSP库进行Three.js网格组合
  10. 计算海洋声学---射线理论注解