yangchong 4 gadi atpakaļ
vecāks
revīzija
525fa214be

+ 22 - 1
VideoView/src/main/java/com/yc/videoview/FloatPhone.java

@@ -20,7 +20,9 @@ public class FloatPhone extends FloatView {
 
     FloatPhone(Context applicationContext) {
         mContext = applicationContext;
-        mWindowManager = (WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE);
+        //创建WindowManager
+        mWindowManager = (WindowManager)
+                applicationContext.getSystemService(Context.WINDOW_SERVICE);
         mLayoutParams = new WindowManager.LayoutParams();
     }
 
@@ -34,12 +36,29 @@ public class FloatPhone extends FloatView {
     public void setView(View view) {
         int layoutType;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            //Android 8.0以后不允许使用一下窗口类型来在其他应用和窗口上方显示提醒窗口
+            //TYPE_PHONE
+            //TYPE_PRIORITY_PHONE
+            //TYPE_SYSTEM_ALERT
+            //TYPE_SYSTEM_OVERLAY
+            //TYPE_SYSTEM_ERROR
+            //如果需要实现在其他应用和窗口上方显示提醒窗口,那么必须该为TYPE_APPLICATION_OVERLAY的类型。
             layoutType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
         } else {
+            //在Android 8.0之前,悬浮窗口设置可以为TYPE_PHONE,这种类型是用于提供用户交互操作的非应用窗口。
+            //Android 8.0以上版本你继续使用TYPE_PHONE类型的悬浮窗口,则会出现如下异常信息:
+            //android.view.WindowManager$BadTokenException:
+            //Unable to add window android.view.ViewRootImpl$W@f8ec928 -- permission denied for window type 2002
             layoutType = WindowManager.LayoutParams.TYPE_PHONE;
         }
         mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        //宽高自适应
+        mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
+        mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+        //设置
+        mLayoutParams.format = PixelFormat.TRANSPARENT;
+        //设置类型
         mLayoutParams.type = layoutType;
         mLayoutParams.windowAnimations = 0;
         mView = view;
@@ -57,7 +76,9 @@ public class FloatPhone extends FloatView {
     public void init() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
             if (WindowUtil.hasPermission(mContext)) {
+                //设置bitmap的格式
                 mLayoutParams.format = PixelFormat.RGBA_8888;
+                //将悬浮窗控件添加到WindowManager
                 mWindowManager.addView(mView, mLayoutParams);
             } else {
                 PermissionActivity.request(mContext, new PermissionActivity.PermissionListener() {

+ 3 - 2
VideoView/src/main/java/com/yc/videoview/IFloatWindowImpl.java

@@ -43,7 +43,8 @@ public class IFloatWindowImpl extends IFloatWindow {
         mFloatView.setSize(mB.mWidth, mB.mHeight);
         mFloatView.setGravity(mB.gravity, mB.xOffset, mB.yOffset);
         mFloatView.setView(mB.mView);
-        mFloatLifecycle = new FloatLifecycle(mB.mApplicationContext, mB.mShow, mB.mActivities, new LifecycleListener() {
+        mFloatLifecycle = new FloatLifecycle(mB.mApplicationContext,
+                mB.mShow, mB.mActivities, new LifecycleListener() {
             @Override
             public void onShow() {
                 show();
@@ -174,7 +175,7 @@ public class IFloatWindowImpl extends IFloatWindow {
         }
     }
 
-    private View.OnTouchListener onTouchListener = new View.OnTouchListener() {
+    private final View.OnTouchListener onTouchListener = new View.OnTouchListener() {
         float lastX, lastY, changeX, changeY;
         int newX, newY;
         @Override

+ 42 - 2
VideoView/wiki/01.全局悬浮窗实践.md

@@ -2,6 +2,7 @@
 - 01.全局悬浮窗介绍
 - 02.悬浮窗注意要点
 - 03.绘制悬浮窗步骤
+- 04.悬浮窗遇到的问题
 
 
 
@@ -31,13 +32,31 @@
     }
     ```
 
+
 ### 02.悬浮窗注意要点
+- 应用内悬浮窗实现流程
+    - 获取WindowManager
+    - 创建悬浮View
+    - 设置悬浮View的拖拽事件
+    - 添加View到WindowManager中
 
 
 
 
 ### 03.绘制悬浮窗步骤
+#### 3.1 获取WindowManager
+- 首先创建WindowManager
+    ```
+    //创建WindowManager
+    windowManager = (WindowManager)
+            applicationContext.getSystemService(Context.WINDOW_SERVICE);
+    layoutParams = new WindowManager.LayoutParams();
+    ```
+
+#### 3.2 LayoutParam设置
 - 全局的悬浮窗是通过WindowManager来绘制已达到能够全局显示的效果,而WindowManager的addView方法还需要一个WindowManager.LayoutParam对象作为参数,此处Android 8.0之后的需要适配一下:
+    - WindowManager的addView方法有两个参数,一个是需要加入的控件对象,另一个参数是WindowManager.LayoutParam对象。
+    - 这里需要着重说明的是LayoutParam里的type变量。这个变量是用来指定窗口类型的。在设置这个变量时,需要注意一个坑,那就是需要对不同版本的Android系统进行适配。
     ```
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
       layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
@@ -45,7 +64,22 @@
       layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
     }
     ```
-- 为了能够使悬浮窗脱离activity全局显示,因此这里使用Service来启动悬浮窗。界面触发悬浮窗代码如下:
+- 在Android 8.0之前,悬浮窗口设置可以为TYPE_PHONE,这种类型是用于提供用户交互操作的非应用窗口。
+    - 而Android 8.0对系统和API行为做了修改,包括使用SYSTEM_ALERT_WINDOW权限的应用无法再使用一下窗口类型来在其他应用和窗口上方显示提醒窗口:
+        - TYPE_PHONE
+        - TYPE_PRIORITY_PHONE
+        - TYPE_SYSTEM_ALERT
+        - TYPE_SYSTEM_OVERLAY
+        - TYPE_SYSTEM_ERROR
+    - 如果需要实现在其他应用和窗口上方显示提醒窗口,那么必须该为TYPE_APPLICATION_OVERLAY的新类型。
+    - 如果在Android 8.0以上版本仍然使用TYPE_PHONE类型的悬浮窗口,则会出现如下异常信息:
+    ```
+    android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@f8ec928 -- permission denied for window type 2002
+    ```
+
+
+#### 3.3 添加悬浮窗操作
+- 界面触发悬浮窗代码如下:
     ```
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {
         // 获取WindowManager服务
@@ -73,7 +107,10 @@
         windowManager.addView(view, layoutParams);
     }
     ```
-- 手指滑动
+
+
+#### 4.4 增加拖动功能
+- 手指滑动,需要更新悬浮窗的位置
     ```
     private class FloatingOnTouchListener implements View.OnTouchListener {
         private int x;
@@ -108,5 +145,8 @@
     ```
 
 
+### 04.悬浮窗遇到的问题
+
+