码迷,mamicode.com
首页 > 其他好文 > 详细

悬浮窗的另外一种使用

时间:2016-06-14 15:43:25      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:

转自: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"/>  

悬浮窗的另外一种使用

标签:

原文地址:http://www.cnblogs.com/fengchuxiaodai/p/5583896.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!