zoukankan      html  css  js  c++  java
  • 悬浮窗的另外一种使用

    转自:http://blog.csdn.net/shinay/article/details/7783276

    下面是创建悬浮窗的方法:

    [java] view plain copy
     
    1. private boolean isAdded = false// 是否已增加悬浮窗  
    2. private static WindowManager wm;  
    3. private static WindowManager.LayoutParams params;  
    4. private Button btn_floatView;  
    [java] view plain copy
     
    1. /** 
    2.  * 创建悬浮窗 
    3.  */  
    4. private void createFloatView() {  
    5.     btn_floatView = new Button(getApplicationContext());  
    6.        btn_floatView.setText("悬浮窗");  
    7.          
    8.        wm = (WindowManager) getApplicationContext()  
    9.         .getSystemService(Context.WINDOW_SERVICE);  
    10.        params = new WindowManager.LayoutParams();  
    11.          
    12.        // 设置window type  
    13.        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;  
    14.        /* 
    15.         * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 
    16.         * 那么优先级会降低一些, 即拉下通知栏不可见 
    17.         */  
    18.          
    19.        params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明  
    20.          
    21.        // 设置Window flag  
    22.        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL  
    23.                              | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;  
    24.        /* 
    25.         * 下面的flags属性的效果形同“锁定”。 
    26.         * 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。 
    27.        wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL 
    28.                               | LayoutParams.FLAG_NOT_FOCUSABLE 
    29.                               | LayoutParams.FLAG_NOT_TOUCHABLE; 
    30.         */  
    31.          
    32.        // 设置悬浮窗的长得宽  
    33.        params.width = 100;  
    34.        params.height = 100;  
    35.          
    36.        // 设置悬浮窗的Touch监听  
    37.        btn_floatView.setOnTouchListener(new OnTouchListener() {  
    38.         int lastX, lastY;  
    39.         int paramX, paramY;  
    40.           
    41.         public boolean onTouch(View v, MotionEvent event) {  
    42.             switch(event.getAction()) {  
    43.             case MotionEvent.ACTION_DOWN:  
    44.                 lastX = (int) event.getRawX();  
    45.                 lastY = (int) event.getRawY();  
    46.                 paramX = params.x;  
    47.                 paramY = params.y;  
    48.                 break;  
    49.             case MotionEvent.ACTION_MOVE:  
    50.                 int dx = (int) event.getRawX() - lastX;  
    51.                 int dy = (int) event.getRawY() - lastY;  
    52.                 params.x = paramX + dx;  
    53.                 params.y = paramY + dy;  
    54.                 // 更新悬浮窗位置  
    55.                 wm.updateViewLayout(btn_floatView, params);  
    56.                 break;  
    57.             }  
    58.             return true;  
    59.         }  
    60.     });  
    61.          
    62.        wm.addView(btn_floatView, params);  
    63.        isAdded = true;  
    64. }  


    做完这步,基本上就可以在桌面显示一个悬浮窗并且可以自由拖动了。

    如果想要控制它在桌面显示,而进入到别的应用程序时隐藏它的话,就需要用一个后台运行的Service来实现了。

    首先需要先获取到手机上的桌面程序的包名(桌面程序指的是按下HOME键所列出的程序,如go桌面等):

    [java] view plain copy
     
    1. /**  
    2.  * 获得属于桌面的应用的应用包名称  
    3.  * @return 返回包含所有包名的字符串列表  
    4.  */  
    5. private List<String> getHomes() {  
    6.     List<String> names = new ArrayList<String>();    
    7.     PackageManager packageManager = this.getPackageManager();    
    8.     // 属性    
    9.     Intent intent = new Intent(Intent.ACTION_MAIN);    
    10.     intent.addCategory(Intent.CATEGORY_HOME);    
    11.     List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,    
    12.             PackageManager.MATCH_DEFAULT_ONLY);    
    13.     for(ResolveInfo ri : resolveInfo) {    
    14.         names.add(ri.activityInfo.packageName);    
    15.     }  
    16.     return names;    
    17. }  


    接着是判断当前运行的Activity是否为桌面应用程序,这里需要用到ActivityManager:

    [java] view plain copy
     
    1. /**  
    2.  * 判断当前界面是否是桌面  
    3.  */    
    4. public boolean isHome(){    
    5.     if(mActivityManager == null) {  
    6.         mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);    
    7.     }  
    8.     List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);    
    9.     return homeList.contains(rti.get(0).topActivity.getPackageName());    
    10. }  


    有了上面两个方法,就可以实现这个功能了。只不过我们需要定时去判断,例如可以用一个Handler每一秒去检查一次:

    [java] view plain copy
     
    1. private Handler mHandler = new Handler() {  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         switch(msg.what) {  
    5.         case HANDLE_CHECK_ACTIVITY:  
    6.             if(isHome()) {  
    7.                 if(!isAdded) {  
    8.                     wm.addView(btn_floatView, params);  
    9.                     isAdded = true;  
    10.                 }  
    11.             } else {  
    12.                 if(isAdded) {  
    13.                     wm.removeView(btn_floatView);  
    14.                     isAdded = false;  
    15.                 }  
    16.             }  
    17.             mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);  
    18.             break;  
    19.         }  
    20.     }  
    21. };  


    在我的Demo中,悬浮窗都是通过Service来控制的,那么我的启动与隐藏就都扔给Service处理就OK。

    [java] view plain copy
     
    1. public void onClick(View v) {  
    2.     switch(v.getId()) {  
    3.     case R.id.btn_show:  
    4.         Intent show = new Intent(this, FloatingWindowService.class);  
    5.         show.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_SHOW);  
    6.         startService(show);  
    7.         break;  
    8.     case R.id.btn_hide:  
    9.         Intent hide = new Intent(this, FloatingWindowService.class);  
    10.         hide.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_HIDE);  
    11.         startService(hide);  
    12.         break;  
    13.     }  
    14. }  


    在Service里的onStart方法中,只需要根据传过来的操作参数,对handler检查进行操作即可。

    [java] view plain copy
     
    1. @Override  
    2. public void onStart(Intent intent, int startId) {  
    3.     super.onStart(intent, startId);  
    4.       
    5.     int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);  
    6.     switch(operation) {  
    7.     case OPERATION_SHOW:  
    8.         mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);  
    9.         mHandler.sendEmptyMessage(HANDLE_CHECK_ACTIVITY);  
    10.         break;  
    11.     case OPERATION_HIDE:  
    12.         mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);  
    13.         break;  
    14.     }  
    15. }  

     

     

     

    另外:需要增加以下权限!!

     

    [html] view plain copy
     
    1. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>  
    2. <uses-permission android:name="android.permission.GET_TASKS"/>  

    下面是创建悬浮窗的方法:

    [java] view plain copy
     
    1. private boolean isAdded = false// 是否已增加悬浮窗  
    2. private static WindowManager wm;  
    3. private static WindowManager.LayoutParams params;  
    4. private Button btn_floatView;  
    [java] view plain copy
     
    1. /** 
    2.  * 创建悬浮窗 
    3.  */  
    4. private void createFloatView() {  
    5.     btn_floatView = new Button(getApplicationContext());  
    6.        btn_floatView.setText("悬浮窗");  
    7.          
    8.        wm = (WindowManager) getApplicationContext()  
    9.         .getSystemService(Context.WINDOW_SERVICE);  
    10.        params = new WindowManager.LayoutParams();  
    11.          
    12.        // 设置window type  
    13.        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;  
    14.        /* 
    15.         * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 
    16.         * 那么优先级会降低一些, 即拉下通知栏不可见 
    17.         */  
    18.          
    19.        params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明  
    20.          
    21.        // 设置Window flag  
    22.        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL  
    23.                              | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;  
    24.        /* 
    25.         * 下面的flags属性的效果形同“锁定”。 
    26.         * 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。 
    27.        wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL 
    28.                               | LayoutParams.FLAG_NOT_FOCUSABLE 
    29.                               | LayoutParams.FLAG_NOT_TOUCHABLE; 
    30.         */  
    31.          
    32.        // 设置悬浮窗的长得宽  
    33.        params.width = 100;  
    34.        params.height = 100;  
    35.          
    36.        // 设置悬浮窗的Touch监听  
    37.        btn_floatView.setOnTouchListener(new OnTouchListener() {  
    38.         int lastX, lastY;  
    39.         int paramX, paramY;  
    40.           
    41.         public boolean onTouch(View v, MotionEvent event) {  
    42.             switch(event.getAction()) {  
    43.             case MotionEvent.ACTION_DOWN:  
    44.                 lastX = (int) event.getRawX();  
    45.                 lastY = (int) event.getRawY();  
    46.                 paramX = params.x;  
    47.                 paramY = params.y;  
    48.                 break;  
    49.             case MotionEvent.ACTION_MOVE:  
    50.                 int dx = (int) event.getRawX() - lastX;  
    51.                 int dy = (int) event.getRawY() - lastY;  
    52.                 params.x = paramX + dx;  
    53.                 params.y = paramY + dy;  
    54.                 // 更新悬浮窗位置  
    55.                 wm.updateViewLayout(btn_floatView, params);  
    56.                 break;  
    57.             }  
    58.             return true;  
    59.         }  
    60.     });  
    61.          
    62.        wm.addView(btn_floatView, params);  
    63.        isAdded = true;  
    64. }  


    做完这步,基本上就可以在桌面显示一个悬浮窗并且可以自由拖动了。

    如果想要控制它在桌面显示,而进入到别的应用程序时隐藏它的话,就需要用一个后台运行的Service来实现了。

    首先需要先获取到手机上的桌面程序的包名(桌面程序指的是按下HOME键所列出的程序,如go桌面等):

    [java] view plain copy
     
    1. /**  
    2.  * 获得属于桌面的应用的应用包名称  
    3.  * @return 返回包含所有包名的字符串列表  
    4.  */  
    5. private List<String> getHomes() {  
    6.     List<String> names = new ArrayList<String>();    
    7.     PackageManager packageManager = this.getPackageManager();    
    8.     // 属性    
    9.     Intent intent = new Intent(Intent.ACTION_MAIN);    
    10.     intent.addCategory(Intent.CATEGORY_HOME);    
    11.     List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,    
    12.             PackageManager.MATCH_DEFAULT_ONLY);    
    13.     for(ResolveInfo ri : resolveInfo) {    
    14.         names.add(ri.activityInfo.packageName);    
    15.     }  
    16.     return names;    
    17. }  


    接着是判断当前运行的Activity是否为桌面应用程序,这里需要用到ActivityManager:

    [java] view plain copy
     
    1. /**  
    2.  * 判断当前界面是否是桌面  
    3.  */    
    4. public boolean isHome(){    
    5.     if(mActivityManager == null) {  
    6.         mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);    
    7.     }  
    8.     List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);    
    9.     return homeList.contains(rti.get(0).topActivity.getPackageName());    
    10. }  


    有了上面两个方法,就可以实现这个功能了。只不过我们需要定时去判断,例如可以用一个Handler每一秒去检查一次:

    [java] view plain copy
     
    1. private Handler mHandler = new Handler() {  
    2.     @Override  
    3.     public void handleMessage(Message msg) {  
    4.         switch(msg.what) {  
    5.         case HANDLE_CHECK_ACTIVITY:  
    6.             if(isHome()) {  
    7.                 if(!isAdded) {  
    8.                     wm.addView(btn_floatView, params);  
    9.                     isAdded = true;  
    10.                 }  
    11.             } else {  
    12.                 if(isAdded) {  
    13.                     wm.removeView(btn_floatView);  
    14.                     isAdded = false;  
    15.                 }  
    16.             }  
    17.             mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);  
    18.             break;  
    19.         }  
    20.     }  
    21. };  


    在我的Demo中,悬浮窗都是通过Service来控制的,那么我的启动与隐藏就都扔给Service处理就OK。

    [java] view plain copy
     
    1. public void onClick(View v) {  
    2.     switch(v.getId()) {  
    3.     case R.id.btn_show:  
    4.         Intent show = new Intent(this, FloatingWindowService.class);  
    5.         show.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_SHOW);  
    6.         startService(show);  
    7.         break;  
    8.     case R.id.btn_hide:  
    9.         Intent hide = new Intent(this, FloatingWindowService.class);  
    10.         hide.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_HIDE);  
    11.         startService(hide);  
    12.         break;  
    13.     }  
    14. }  


    在Service里的onStart方法中,只需要根据传过来的操作参数,对handler检查进行操作即可。

    [java] view plain copy
     
    1. @Override  
    2. public void onStart(Intent intent, int startId) {  
    3.     super.onStart(intent, startId);  
    4.       
    5.     int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);  
    6.     switch(operation) {  
    7.     case OPERATION_SHOW:  
    8.         mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);  
    9.         mHandler.sendEmptyMessage(HANDLE_CHECK_ACTIVITY);  
    10.         break;  
    11.     case OPERATION_HIDE:  
    12.         mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);  
    13.         break;  
    14.     }  
    15. }  

     

     

     

    另外:需要增加以下权限!!

     

    [html] view plain copy
     
    1. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>  
    2. <uses-permission android:name="android.permission.GET_TASKS"/>  
  • 相关阅读:
    5招教你实现多线程场景下的线程安全!
    跟我读论文丨ACL2021 NER BERT化隐马尔可夫模型用于多源弱监督命名实体识别
    大数据集群跨多版本升级、业务0中断,只因背后有TA
    云小课 | 到底什么是区块链?
    信创产业已成现象级新风口,快来加入争做“弄潮儿”
    教你如何使用FusionInsight SqoopShell
    【Kubernetes】镜像拉取策略-IfNotPresent
    【Kubernetes】镜像拉取策略-Always
    【Kubernetes】env 注入资源
    【Kubernetes】env 注入字段值
  • 原文地址:https://www.cnblogs.com/fengchuxiaodai/p/5583896.html
Copyright © 2011-2022 走看看