下面实现最小化悬窗,点击继续悬窗播放,拖动小火箭效果。
这部分代码借鉴了网上的小火箭效果
点击悬窗视频的一个按钮启动另一个server。展现小按钮图标。
case R.id.iv_small:
MyApplicaton.setValueProgress(valueProgress);
onExit();
Intent i = new Intent(context, FloatWindowService.class);
context.startService(i);
break;
下面看FloatWindowService里面代码。createSmallWindow创建小悬浮窗。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyWindowManager.createSmallWindow(getApplicationContext());
return super.onStartCommand(intent, flags, startId);
}
MyWindowManager中的方法
//小悬浮窗View的实例
private static FloatWindowSmallView smallWindow;
/**
* 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。
*/
public static void createSmallWindow(Context context) {
WindowManager windowManager = getWindowManager(context);
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
if (smallWindow == null) {
smallWindow = new FloatWindowSmallView(context);
if (smallWindowParams == null) {
smallWindowParams = new LayoutParams();
smallWindowParams.type = LayoutParams.TYPE_SYSTEM_ALERT;
smallWindowParams.format = PixelFormat.RGBA_8888;
smallWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
smallWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
smallWindowParams.width = FloatWindowSmallView.windowViewWidth;
smallWindowParams.height = FloatWindowSmallView.windowViewHeight;
smallWindowParams.x = screenWidth;
smallWindowParams.y = screenHeight / 2;
}
smallWindow.setParams(smallWindowParams);
windowManager.addView(smallWindow, smallWindowParams);
}
}
/**
* 将小悬浮窗从屏幕上移除。
*/
public static void removeSmallWindow(Context context) {
if (smallWindow != null) {
WindowManager windowManager = getWindowManager(context);
windowManager.removeView(smallWindow);
smallWindow = null;
}
}
private static WindowManager getWindowManager(Context context) {
if (mWindowManager == null) {
mWindowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
}
return mWindowManager;
}
创建小火箭的代码如下:
/**
* 创建一个火箭发射台,位置为屏幕底部。
*/
public static void createLauncher(Context context) {
WindowManager windowManager = getWindowManager(context);
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
if (rocketLauncher == null) {
rocketLauncher = new RocketLauncher(context);
if (launcherParams == null) {
launcherParams = new LayoutParams();
launcherParams.x = screenWidth / 2 - RocketLauncher.width / 2;
launcherParams.y = screenHeight - RocketLauncher.height;
launcherParams.type = LayoutParams.TYPE_PHONE;
launcherParams.format = PixelFormat.RGBA_8888;
launcherParams.gravity = Gravity.LEFT | Gravity.TOP;
launcherParams.width = RocketLauncher.width;
launcherParams.height = RocketLauncher.height;
}
windowManager.addView(rocketLauncher, launcherParams);
}
}
/**
* 将火箭发射台从屏幕上移除。
*/
public static void removeLauncher(Context context) {
if (rocketLauncher != null) {
WindowManager windowManager = getWindowManager(context);
windowManager.removeView(rocketLauncher);
rocketLauncher = null;
}
}
/**
* 更新火箭发射台的显示状态。
*/
public static void updateLauncher() {
if (rocketLauncher != null) {
rocketLauncher.updateLauncherStatus(isReadyToLaunch());
}
}
/**
* 判断小火箭是否准备好发射了。
*
* @return 当火箭被发到发射台上返回true,否则返回false。
*/
public static boolean isReadyToLaunch() {
if ((smallWindowParams.x > launcherParams.x && smallWindowParams.x
+ smallWindowParams.width < launcherParams.x
+ launcherParams.width)
&& (smallWindowParams.y + smallWindowParams.height > launcherParams.y)) {
return true;
}
return false;
}
下面看FloatWindowSmallView 里面的代码
主要是onTouchEvent方法
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isPressed = true;
// 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度
xInView = event.getX();
yInView = event.getY();
xDownInScreen = event.getRawX();
yDownInScreen = event.getRawY() - getStatusBarHeight();
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
break;
case MotionEvent.ACTION_MOVE:
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
// 手指移动的时候更新小悬浮窗的状态和位置
updateViewStatus();
updateViewPosition();
break;
case MotionEvent.ACTION_UP:
isPressed = false;
if (MyWindowManager.isReadyToLaunch()) {
launchRocket();//符合则发射
} else {
updateViewStatus();
// 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。
if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {
openFloatMovie();
}
}
break;
default:
break;
}
return true;
}
/**
* 用于发射小火箭。
*/
private void launchRocket() {
MyWindowManager.removeLauncher(getContext());
new LaunchTask().execute();
}
/**
* 开始执行发射小火箭的任务。
*
* @author guolin
*/
class LaunchTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
// 在这里对小火箭的位置进行改变,从而产生火箭升空的效果
while (mParams.y > 0) {
mParams.y = mParams.y - 10;
publishProgress();
try {
Thread.sleep(8);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
windowManager.updateViewLayout(FloatWindowSmallView.this, mParams);
}
@Override
protected void onPostExecute(Void result) {
// 火箭升空结束后,回归到悬浮窗状态
updateViewStatus();
openFloatMovie();
}
private void openFloatMovie() {
Intent mIntent = new Intent("createUI");
mIntent.setClass(getContext(), MediaPlaybackService.class);
getContext().startService(mIntent);
MyWindowManager.removeSmallWindow(getContext());
}
}
/**
* 更新小悬浮窗在屏幕中的位置。
*/
private void updateViewPosition() {
mParams.x = (int) (xInScreen - xInView);
mParams.y = (int) (yInScreen - yInView);
windowManager.updateViewLayout(this, mParams);
MyWindowManager.updateLauncher();
}
/**
* 更新View的显示状态,判断是显示悬浮窗还是小火箭。
*/
private void updateViewStatus() {
if (isPressed && rocketImg.getVisibility() != View.VISIBLE) {
mParams.width = rocketWidth;
mParams.height = rocketHeight;
windowManager.updateViewLayout(this, mParams);
smallWindowLayout.setVisibility(View.GONE);
rocketImg.setVisibility(View.VISIBLE);
MyWindowManager.createLauncher(getContext());
} else if (!isPressed) {
mParams.width = windowViewWidth;
mParams.height = windowViewHeight;
windowManager.updateViewLayout(this, mParams);
smallWindowLayout.setVisibility(View.VISIBLE);
rocketImg.setVisibility(View.GONE);
MyWindowManager.removeLauncher(getContext());
}
}
/**
* 用于获取状态栏的高度。
*
* @return 返回状态栏高度的像素值。
*/
private int getStatusBarHeight() {
if (statusBarHeight == 0) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object o = c.newInstance();
Field field = c.getField("status_bar_height");
int x = (Integer) field.get(o);
statusBarHeight = getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
}
return statusBarHeight;
}
时间: 2024-10-09 21:30:24