您的位置:首页 > 其它

悬窗播放视频,让你聊天看视频两不误(上)

2017-03-02 15:34 351 查看
当年的毕业设计拿出来记录一下,实现效果图如下:



视频播放用的是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" />
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: