之前接了需求要让视频播放时可以像优酷视频那样在悬浮窗里播放,并且悬浮窗和主播放页面之间要实现无缝切换,项目中使用的是自封装的ijkplayer
这个要求就代表不能在悬浮窗中新建视频控件,所以需要在悬浮窗中复用主页面的视频控件,以达到无缝衔接的效果。
主页面对应的视频控件的父view
<FrameLayout 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);
可以让播放界面退到后台而整个应用不会退回后台
权限请求
要使用悬浮窗需要申请权限
<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() { @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,可通过自定义获得自己想要的效果
<FrameLayout 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"> <FrameLayout android:id="@+id/floating_video" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageView 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" /> <ImageView android: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; @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 优酷视频悬浮窗播放内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
本文向大家介绍Android仿微信视屏悬浮窗效果,包括了Android仿微信视屏悬浮窗效果的使用技巧和注意事项,需要的朋友参考一下 在项目中需要对接入的腾讯云音视频,可以悬浮窗显示,悬浮窗可拖拽,并且在悬浮窗不影响其他的activity的焦点。 这个大神的文章Android基于腾讯云实时音视频仿微信视频通话最小化悬浮,他讲的是视频通话时,将远端视频以悬浮窗形式展示,根据他的代码我进行了部分简化 1
本文向大家介绍Android仿微信文章悬浮窗效果的实现代码,包括了Android仿微信文章悬浮窗效果的实现代码的使用技巧和注意事项,需要的朋友参考一下 序言 前些日子跟朋友聊天,朋友Z果粉,前些天更新了微信,说微信出了个好方便的功能啊,我问是啥功能啊,看看我大Android有没有,他说现在阅读公众号文章如果有人给你发微信你可以把这篇文章当作悬浮窗悬浮起来,方便你聊完天不用找继续阅读,听完是不是觉得
有人可以帮助使用这个代码来播放嵌入网站的youtube视频吗?我试过各种方法,包括硬件加速=True。 webview显示了youtube页面和缩略图,但点击它们时什么也不会发生。 在某些硬件加速的设备上,它只播放声音,但不播放视频。谢谢大家!
问题内容: 我在android中实现了视频播放,这对android来说是全新的,这是我到目前为止收集的部分代码。 根据逻辑,它应该播放视频。不知道我在哪里做错了。 问题答案:
我正在开发一个应用程序,它使用webview来显示网页,如果url是视频链接(youtube)或作为网页一部分的视频,我想播放视频。我试着把url直接添加到webview中,但它连youtube链接都不播放,我已经在webview中启用了插件和javascript.....有谁能在这个问题上帮我,
我们正在使用在Xamarin中构建一个应用程序。在应用程序中,我们需要播放视频,因此我们为此编写了一些代码。但是,视频没有播放,在Android上应用程序崩溃,同时抛出一个通用错误。 这是代码: 视频容器。反恐精英 VideoViewRender。反恐精英 所发生的情况是,被记录到控制台,但没有。我们从Xamarin论坛获得了这段代码,但未能成功实现。我们做错了什么?
视频直播App播放器优化 Android 设置 IOS 设置
本文向大家介绍Android实现带磁性的悬浮窗体效果,包括了Android实现带磁性的悬浮窗体效果的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android实现带磁性的悬浮窗体效果。分享给大家供大家参考,具体如下: 带磁性的悬浮窗体,类似于360绿色小人 主要实现的是: 1.悬浮所有窗体之上 2.有吸引力,吸附于屏幕边上 3.有点击效果 下面我就实现上面三点,简单封装了个FloatVi