nowindxdw
11/2/2017 - 7:53 AM

android 画中画实现

今天继续上一篇Android顶层窗口、浮动窗口的进阶应用。上一篇主要讲解了WindowManager服务和如何使用WindowManager编写一个顶层窗口。今天主要是讲讲如何在顶层窗口里面播放视频,这个功能对很多嵌入式设备来说十分有用。例如现在手机和平板上一些视频播放器就可以实现画中画功能,只显示一部分小窗口播放,用户可以继续操作其他功能。当你在看视频的时候收到短信,你只要进入画中画功能,视频可以继续播放,同时你可以去操作短信功能。

(PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)
 
1、MediaPlayer视频播放
  视频播放使用Android自带的播放功能,下面简单介绍一下MediaPlayer的使用。MediaPlayer使用其实十分方便,不过它支持的格式并不多,不过这里主要是为了演示如何实现画中画功能。因为后面打算把这个画中画功能加入到VLC播放器里面,这样就可以解决支持格式不多问题。
//Edited by mythou
//http://www.cnblogs.com/mythou/
// 播放界面使用surfaceview实现        surfaceView = (SurfaceView) mlayoutView.findViewById(R.id.myView);//获取surfaceHolder,控制surfaceviewsurfaceHolder = surfaceView.getHolder();//回调,检测surfaceview的三种状态surfaceHolder.addCallback(this);//surfaceview的显示源类型surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//mediaplayer初始化mediaPlayer = new MediaPlayer();//设置不同的监听接口mediaPlayer.setOnCompletionListener(this);mediaPlayer.setOnErrorListener(this);mediaPlayer.setOnPreparedListener(this);mediaPlayer.setOnSeekCompleteListener(this);mediaPlayer.setOnVideoSizeChangedListener(this);String filePath = "/mnt/card/test.mp4";// "/mnt/sdcard/test.mp4";//                                                // 本地地址和网络地址都可以try{     mediaPlayer.setDataSource(filePath);} catch (IllegalArgumentException e){    // TODO: handle exception    Log.v(LOGCAT, e.getMessage());    onExit();}
  上面是初始化surfaceView和MeidaPlayer的代码,surfaceview在android应用开发里面十分重要,基本上设计视频或者动画类型的界面,都需要用到它。如果不了解的朋友,建议好好去熟悉一下这个类的使用。下面我们看看surfaceview的回调接口:
//Edited by mythou
//http://www.cnblogs.com/mythou/
  @Override    public void surfaceCreated(SurfaceHolder holder)    {        Log.v(LOGCAT, "suc calles");        mediaPlayer.setDisplay(holder);// 若无次句,将只有声音而无图像        try        {
       //播放视频            mediaPlayer.prepare();        } catch (IllegalStateException e)        {            onExit();        } catch (IOException e)        {            onExit();        }
  }
  上面是surfaceview里面其中一个回调接口,在这里我们处理视频准备开始播放,以及把surfaceview设置到MediaPlayer里面,让他们两者协调工作。播放的功能是MediaPlayer实现,而画面显示是依赖surfaceview实现。
 
 2、设置WindowManager窗口
  
//Edited by mythou
//http://www.cnblogs.com/mythou/
  public void initWindow()    {        // 获取WindowManager        wm = (WindowManager) context.getApplicationContext().getSystemService(                "window");        // 设置LayoutParams(全局变量)相关参数        // wmParams = ((MyApplication)getApplication()).getMywmParams();        wmParams = new WindowManager.LayoutParams();        /**         * 以下都是WindowManager.LayoutParams的相关属性 具体用途可参考SDK文档         */        wmParams.type = /*LayoutParams.TYPE_SYSTEM_ALERT | */LayoutParams.TYPE_SYSTEM_OVERLAY; // 设置window type        // 设置图片格式,效果为背景透明        wmParams.format = PixelFormat.TRANSPARENT;        // 设置Window flag        wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL                | LayoutParams.FLAG_NOT_FOCUSABLE                | LayoutParams.FLAG_LAYOUT_NO_LIMITS;        /*         * 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。         * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL |         * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE;         */        wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至左上角        // 以屏幕左上角为原点,设置x、y初始值        currentDisplay = wm.getDefaultDisplay();        WIDTH = currentDisplay.getWidth();        HEIGHT = currentDisplay.getHeight();        wmParams.x = (WIDTH - VIEW_WIDTH) / 2;        wmParams.y = 0;        // 设置悬浮窗口长宽数据        wmParams.width = VIEW_WIDTH;        wmParams.height = VIEW_HEIGHT;    }
上面是使用WindowManager设置浮动窗口流程,跟我们上一篇界面的方法一致,具体不了解的朋友,可以看看我上一篇文章。
 
3、界面绑定画面
  下面我们看看如何把我们的视频播放界面绑定到顶层显示View上面,上一篇已经介绍过,只需要调用addview方法即可。
//Edited by mythou
//http://www.cnblogs.com/mythou/
MyFloatView sFloatView;ViewGroup fView;//绑定XML配置的界面fView = (ViewGroup) View.inflate(context, R.layout.main, null);// 显示myFloatView图像sFloatView = new MyFloatView(fView);sFloatView.bindViewListener();sFloatView.showLayoutView();
  上面是通过配置一个XML来显示界面,XML界面里面定义了Surfaceview类,最后在FloatView里面的showLayoutView调用WindowManager的addView添加到窗口服务里面。
public void showLayoutView(){    wm.addView(mlayoutView, wmParams);}
  上面就是大概的显示绑定流程,具体详细代码,请查看Demo里面的代码。这个Demo是在CSDN上面下载的,本来是想自己写一个,不过既然有开发者已经分享出来,我就没有重新自己写了,这个Demo我修改了一些错误,原版下载的,导入后会关联一个工程导致出错,修正了这个问题。下载我下面的代码,直接导入就可以使用。然后设置一下视频路径。
  这只是一个很简单功能,视频路径也是写死了,只是让大家知道如何实现画中画功能。可以把这功能移植到我们的多媒体播放器上面实现视频的画中画播放。


自定义TOPBAR
http://www.imooc.com/wenda/detail/240863