悬窗播放视频,让你聊天看视频两不误(上)
2017-03-02 15:34
351 查看
当年的毕业设计拿出来记录一下,实现效果图如下:
视频播放用的是vitamio框架。这里只讨论实现悬浮窗播放视频的思路
1.点击视频播放器中的悬窗按钮,开启悬窗播放模式。这里启动了一个后台server。
先进入Home桌面,然后启动MediaPlaybackService
然后我们来看MediaPlaybackService中做了什么
当action为createUI的时候创建UI窗口,当为removeUI的时候销毁窗口
createView方法中实例化MyFloatView并传入一个ViewGroup,并调用showLayoutView。
我们在MyFloatView中做实现悬窗的逻辑用WindowManager。
所以我们接下来要做的就是在MyFloatView中使用WindowManager,显示出来传入MyFloatView的ViewGroup
WindowManager的方法很简单,基本用到的就三个addView,removeView,updateViewLayout。
ViewGroup为悬浮的界面 :R.layout.float_main
在MyFloatView中实例化一个播放器,初始化播放器,初始化悬窗。
看initialUI();里面代码 主要是设置videoView
然后是initWindow(); 注释很清楚
实例化之后调用showLayoutView,把ViewGroup加入WindowManager窗口中
然后通过onTouchEvent实现滑动窗口:
5秒不触摸屏幕,去掉控制UI。
关闭窗口的代码如下:
使用悬浮窗记得加权限:
视频播放用的是vitamio框架。这里只讨论实现悬浮窗播放视频的思路
1.点击视频播放器中的悬窗按钮,开启悬窗播放模式。这里启动了一个后台server。
先进入Home桌面,然后启动MediaPlaybackService
Intent intent = new Intent(); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); Intent mIntent = new Intent("createUI"); mIntent.setClass(PlayActivity.this, MediaPlaybackService.class); startService(mIntent);
然后我们来看MediaPlaybackService中做了什么
当action为createUI的时候创建UI窗口,当为removeUI的时候销毁窗口
@Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { String action = intent.getAction(); String cmd = intent.getStringExtra("command"); if ("createUI".equals(action)) { createView(this); } else if ("removeUI".equals(action)) { fView = null; sFloatView = null; } } return START_STICKY; }
createView方法中实例化MyFloatView并传入一个ViewGroup,并调用showLayoutView。
我们在MyFloatView中做实现悬窗的逻辑用WindowManager。
public ViewGroup fView; MyFloatView sFloatView; private void createView(Context context) { if (fView != null) { return; } fView = (ViewGroup) View.inflate(context, R.layout.float_main, null); sFloatView = new MyFloatView(fView); sFloatView.showLayoutView(); }
所以我们接下来要做的就是在MyFloatView中使用WindowManager,显示出来传入MyFloatView的ViewGroup
WindowManager的方法很简单,基本用到的就三个addView,removeView,updateViewLayout。
ViewGroup为悬浮的界面 :R.layout.float_main
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="300dp" android:layout_height="200dp" > <io.vov.vitamio.widget.VideoView android:id="@+id/surfaceView" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> <include layout="@layout/app_video_float"/> </FrameLayout>
在MyFloatView中实例化一个播放器,初始化播放器,初始化悬窗。
private VideoView videoView; public MyFloatView(ViewGroup layoutView) { mlayoutView = layoutView; context = mlayoutView.getContext(); mlayoutView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View paramView, MotionEvent paramMotionEvent) { //mlayoutView.getParent().requestDisallowInterceptTouchEvent(true); onTouchEvent(paramMotionEvent); return false; } }); initialUI(); initWindow(); }
看initialUI();里面代码 主要是设置videoView
private void initialUI() { fLayout=(FrameLayout) mlayoutView.findViewById(R.id.fLayout); videoView=(VideoView) mlayoutView.findViewById(R.id.surfaceView); ImageView iv_fillImageView=(ImageView) mlayoutView.findViewById(R.id.iv_fill); ImageView iv_close=(ImageView) mlayoutView.findViewById(R.id.iv_off); iv_play=(ImageView) mlayoutView.findViewById(R.id.iv_play); ImageView iv_small=(ImageView) mlayoutView.findViewById(R.id.iv_small); seekBar=(SeekBar) mlayoutView.findViewById(R.id.seekBar); int progress=MyApplicaton.getValueProgress(); String pathString=MyApplicaton.getPath(); videoView.setVideoURI(Uri.parse(pathString)); videoView.seekTo(progress); videoView.start(); isPlay = true; videoView.setOnCompletionListener(this); videoView.setOnBufferingUpdateListener(this); videoView.setOnErrorListener(this); videoView.setOnInfoListener(this); videoView.setOnPreparedListener(this); IntentFilter filter = new IntentFilter(ACTION_DESTROY_MOVIE); context.registerReceiver(sReceiver, filter); iv_fillImageView.setOnClickListener(this); iv_close.setOnClickListener(this); iv_play.setOnClickListener(this); iv_small.setOnClickListener(this); setListener(); update = new upDateSeekBar(); new Thread(update).start(); endGesture(); }
然后是initWindow(); 注释很清楚
public void initWindow() { // 获取WindowManager wm = (WindowManager) context.getApplicationContext().getSystemService( "window"); //获取LayoutParams wmParams = new WindowManager.LayoutParams(); //这里是关键 这个FIRST_SYSTEM_WINDOW的值就是2000。2003和2002的区别就在于2003类型的View比2002类型的还要top,能显示在系统下拉状态栏之上! wmParams.type =2002; /*LayoutParams.TYPE_SYSTEM_ALERT | */ //LayoutParams.TYPE_SYSTEM_OVERLAY; // 设置图片格式,效果为背景透明 wmParams.format = PixelFormat.TRANSPARENT; /** *这里的flags也很关键 *代码实际是wmParams.flags |= FLAG_NOT_FOCUSABLE; *40的由来是wmParams的默认属性(32)+ FLAG_NOT_FOCUSABLE(8) */ wmParams.flags =40;// LayoutParams.FLAG_NOT_TOUCH_MODAL // | LayoutParams.FLAG_NOT_FOCUSABLE; //| LayoutParams.FLAG_LAYOUT_NO_LIMITS; // 设置悬浮窗口长宽数据 wmParams.width = VIEW_WIDTH; wmParams.height = VIEW_HEIGHT; wmParams.gravity = Gravity.LEFT | Gravity.TOP; //gravity属性 简单地说,就是窗口如何停靠。当设置了 Gravity.LEFT 或 Gravity.RIGHT 之后,x值就表示到特定边的距离。 //通过WindowManager中的Display获取屏幕大小: currentDisplay = wm.getDefaultDisplay(); WIDTH = currentDisplay.getWidth(); HEIGHT = currentDisplay.getHeight(); wmParams.x = 0;// 以屏幕左上角为原点,设置x、y初始值 wmParams.y = 0; }
实例化之后调用showLayoutView,把ViewGroup加入WindowManager窗口中
public void showLayoutView() { wm.addView(mlayoutView, wmParams); }
然后通过onTouchEvent实现滑动窗口:
public boolean onTouchEvent(MotionEvent event) { x = event.getRawX(); y = event.getRawY()-25; Log.i("currP", "currX"+x+"====currY"+y); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mTouchStartX = event.getX(); mTouchStartY = event.getY(); Log.e("ACTION_DOWN", "ACTION_DOWN"+mTouchStartY+"====ACTION_DOWN"+y); fLayout.setVisibility(View.VISIBLE); break; case MotionEvent.ACTION_MOVE: Log.e("ACTION_MOVE", "ACTION_MOVE"+mTouchStartY+"====ACTION_MOVE"+y); updateViewPosition(); break; case MotionEvent.ACTION_UP: updateViewPosition(); mTouchStartX=mTouchStartY=0; endGesture(); break; } return true; } private void updateViewPosition() { wmParams.x = (int) (x - mTouchStartX); wmParams.y = (int) (y - mTouchStartY); wm.updateViewLayout(mlayoutView, wmParams); }
5秒不触摸屏幕,去掉控制UI。
private void endGesture() { disHandler.removeMessages(1); disHandler.sendEmptyMessageDelayed(1, 5000); } private Handler disHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { fLayout.setVisibility(View.GONE); } } };
关闭窗口的代码如下:
public void onExit() { //MyApplicaton.setValueProgress(valueProgress); if(mlayoutView!=null){ try { wm.removeView(mlayoutView); Intent mIntent = new Intent("removeUI"); mIntent.setClass(context, MediaPlaybackService.class); context.startService(mIntent); context.unregisterReceiver(sReceiver); videoView.stopPlayback(); isPlay = false; isFinish = true; } catch (Exception e) { System.exit(0); } } }
使用悬浮窗记得加权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
相关文章推荐
- 悬窗播放视频,让你聊天看视频两不误(下)
- VC++实现视频聊天:FFmpeg解码+SDL播放视频
- 【PHP-socket框架】MeepoPS轻松构建在线实时聊天, 即时游戏, 视频流媒体播放
- iOS——微信朋友圈小视频的播放和聊天窗口小视频的播放
- im 聊天中视频播放
- iOS微信聊天界面朋友圈多个小视频同时播放不卡顿
- FMS3系列(五):通过FMS实现时时视频聊天(Flash|Flex)
- 使用CVideoPlayerUtility播放视频,在某些型号的手机上只有声音没有图像的问题
- 系统中插入视频聊天
- UE4加载播放网络上的视频
- 传到服务器的 mp4 视频文件没法播放
- 【Unity3d】在Unity3d中播放视频:AVPro Video的使用
- mplayer播放rm或rmvb视频报错
- iOS播放多种格式视频
- Window 下 Qt5 使用QMediaplayer 进行视频播放 流播放问题
- C# WMP 视频播放
- VLC 无法播放视频
- 使用开源框架ijkplayer播放视频,写给新手不走弯路
- Vuforia在ios上全屏播放网络视频的方法
- Android 音视频深入 二 AudioTrack播放pcm(附源码下载)