悬浮窗的另外一种使用
转自:http://blog.csdn.net/shinay/article/details/7783276
下面是创建悬浮窗的方法:
- private boolean isAdded = false; // 是否已增加悬浮窗
 - private static WindowManager wm;
 - private static WindowManager.LayoutParams params;
 - private Button btn_floatView;
 
- /**
 - * 创建悬浮窗
 - */
 - private void createFloatView() {
 - btn_floatView = new Button(getApplicationContext());
 - btn_floatView.setText("悬浮窗");
 - wm = (WindowManager) getApplicationContext()
 - .getSystemService(Context.WINDOW_SERVICE);
 - params = new WindowManager.LayoutParams();
 - // 设置window type
 - params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 - /*
 - * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE;
 - * 那么优先级会降低一些, 即拉下通知栏不可见
 - */
 - params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
 - // 设置Window flag
 - params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
 - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 - /*
 - * 下面的flags属性的效果形同“锁定”。
 - * 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
 - wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL
 - | LayoutParams.FLAG_NOT_FOCUSABLE
 - | LayoutParams.FLAG_NOT_TOUCHABLE;
 - */
 - // 设置悬浮窗的长得宽
 - params.width = 100;
 - params.height = 100;
 - // 设置悬浮窗的Touch监听
 - btn_floatView.setOnTouchListener(new OnTouchListener() {
 - int lastX, lastY;
 - int paramX, paramY;
 - public boolean onTouch(View v, MotionEvent event) {
 - switch(event.getAction()) {
 - case MotionEvent.ACTION_DOWN:
 - lastX = (int) event.getRawX();
 - lastY = (int) event.getRawY();
 - paramX = params.x;
 - paramY = params.y;
 - break;
 - case MotionEvent.ACTION_MOVE:
 - int dx = (int) event.getRawX() - lastX;
 - int dy = (int) event.getRawY() - lastY;
 - params.x = paramX + dx;
 - params.y = paramY + dy;
 - // 更新悬浮窗位置
 - wm.updateViewLayout(btn_floatView, params);
 - break;
 - }
 - return true;
 - }
 - });
 - wm.addView(btn_floatView, params);
 - isAdded = true;
 - }
 
做完这步,基本上就可以在桌面显示一个悬浮窗并且可以自由拖动了。
如果想要控制它在桌面显示,而进入到别的应用程序时隐藏它的话,就需要用一个后台运行的Service来实现了。
首先需要先获取到手机上的桌面程序的包名(桌面程序指的是按下HOME键所列出的程序,如go桌面等):
- /**
 - * 获得属于桌面的应用的应用包名称
 - * @return 返回包含所有包名的字符串列表
 - */
 - private List<String> getHomes() {
 - List<String> names = new ArrayList<String>();
 - PackageManager packageManager = this.getPackageManager();
 - // 属性
 - Intent intent = new Intent(Intent.ACTION_MAIN);
 - intent.addCategory(Intent.CATEGORY_HOME);
 - List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,
 - PackageManager.MATCH_DEFAULT_ONLY);
 - for(ResolveInfo ri : resolveInfo) {
 - names.add(ri.activityInfo.packageName);
 - }
 - return names;
 - }
 
接着是判断当前运行的Activity是否为桌面应用程序,这里需要用到ActivityManager:
- /**
 - * 判断当前界面是否是桌面
 - */
 - public boolean isHome(){
 - if(mActivityManager == null) {
 - mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
 - }
 - List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
 - return homeList.contains(rti.get(0).topActivity.getPackageName());
 - }
 
有了上面两个方法,就可以实现这个功能了。只不过我们需要定时去判断,例如可以用一个Handler每一秒去检查一次:
- private Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - switch(msg.what) {
 - case HANDLE_CHECK_ACTIVITY:
 - if(isHome()) {
 - if(!isAdded) {
 - wm.addView(btn_floatView, params);
 - isAdded = true;
 - }
 - } else {
 - if(isAdded) {
 - wm.removeView(btn_floatView);
 - isAdded = false;
 - }
 - }
 - mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);
 - break;
 - }
 - }
 - };
 
在我的Demo中,悬浮窗都是通过Service来控制的,那么我的启动与隐藏就都扔给Service处理就OK。
- public void onClick(View v) {
 - switch(v.getId()) {
 - case R.id.btn_show:
 - Intent show = new Intent(this, FloatingWindowService.class);
 - show.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_SHOW);
 - startService(show);
 - break;
 - case R.id.btn_hide:
 - Intent hide = new Intent(this, FloatingWindowService.class);
 - hide.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_HIDE);
 - startService(hide);
 - break;
 - }
 - }
 
在Service里的onStart方法中,只需要根据传过来的操作参数,对handler检查进行操作即可。
- @Override
 - public void onStart(Intent intent, int startId) {
 - super.onStart(intent, startId);
 - int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);
 - switch(operation) {
 - case OPERATION_SHOW:
 - mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
 - mHandler.sendEmptyMessage(HANDLE_CHECK_ACTIVITY);
 - break;
 - case OPERATION_HIDE:
 - mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
 - break;
 - }
 - }
 
另外:需要增加以下权限!!
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
 - <uses-permission android:name="android.permission.GET_TASKS"/>
 
下面是创建悬浮窗的方法:
- private boolean isAdded = false; // 是否已增加悬浮窗
 - private static WindowManager wm;
 - private static WindowManager.LayoutParams params;
 - private Button btn_floatView;
 
- /**
 - * 创建悬浮窗
 - */
 - private void createFloatView() {
 - btn_floatView = new Button(getApplicationContext());
 - btn_floatView.setText("悬浮窗");
 - wm = (WindowManager) getApplicationContext()
 - .getSystemService(Context.WINDOW_SERVICE);
 - params = new WindowManager.LayoutParams();
 - // 设置window type
 - params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 - /*
 - * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE;
 - * 那么优先级会降低一些, 即拉下通知栏不可见
 - */
 - params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
 - // 设置Window flag
 - params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
 - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 - /*
 - * 下面的flags属性的效果形同“锁定”。
 - * 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
 - wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL
 - | LayoutParams.FLAG_NOT_FOCUSABLE
 - | LayoutParams.FLAG_NOT_TOUCHABLE;
 - */
 - // 设置悬浮窗的长得宽
 - params.width = 100;
 - params.height = 100;
 - // 设置悬浮窗的Touch监听
 - btn_floatView.setOnTouchListener(new OnTouchListener() {
 - int lastX, lastY;
 - int paramX, paramY;
 - public boolean onTouch(View v, MotionEvent event) {
 - switch(event.getAction()) {
 - case MotionEvent.ACTION_DOWN:
 - lastX = (int) event.getRawX();
 - lastY = (int) event.getRawY();
 - paramX = params.x;
 - paramY = params.y;
 - break;
 - case MotionEvent.ACTION_MOVE:
 - int dx = (int) event.getRawX() - lastX;
 - int dy = (int) event.getRawY() - lastY;
 - params.x = paramX + dx;
 - params.y = paramY + dy;
 - // 更新悬浮窗位置
 - wm.updateViewLayout(btn_floatView, params);
 - break;
 - }
 - return true;
 - }
 - });
 - wm.addView(btn_floatView, params);
 - isAdded = true;
 - }
 
做完这步,基本上就可以在桌面显示一个悬浮窗并且可以自由拖动了。
如果想要控制它在桌面显示,而进入到别的应用程序时隐藏它的话,就需要用一个后台运行的Service来实现了。
首先需要先获取到手机上的桌面程序的包名(桌面程序指的是按下HOME键所列出的程序,如go桌面等):
- /**
 - * 获得属于桌面的应用的应用包名称
 - * @return 返回包含所有包名的字符串列表
 - */
 - private List<String> getHomes() {
 - List<String> names = new ArrayList<String>();
 - PackageManager packageManager = this.getPackageManager();
 - // 属性
 - Intent intent = new Intent(Intent.ACTION_MAIN);
 - intent.addCategory(Intent.CATEGORY_HOME);
 - List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,
 - PackageManager.MATCH_DEFAULT_ONLY);
 - for(ResolveInfo ri : resolveInfo) {
 - names.add(ri.activityInfo.packageName);
 - }
 - return names;
 - }
 
接着是判断当前运行的Activity是否为桌面应用程序,这里需要用到ActivityManager:
- /**
 - * 判断当前界面是否是桌面
 - */
 - public boolean isHome(){
 - if(mActivityManager == null) {
 - mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
 - }
 - List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
 - return homeList.contains(rti.get(0).topActivity.getPackageName());
 - }
 
有了上面两个方法,就可以实现这个功能了。只不过我们需要定时去判断,例如可以用一个Handler每一秒去检查一次:
- private Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - switch(msg.what) {
 - case HANDLE_CHECK_ACTIVITY:
 - if(isHome()) {
 - if(!isAdded) {
 - wm.addView(btn_floatView, params);
 - isAdded = true;
 - }
 - } else {
 - if(isAdded) {
 - wm.removeView(btn_floatView);
 - isAdded = false;
 - }
 - }
 - mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);
 - break;
 - }
 - }
 - };
 
在我的Demo中,悬浮窗都是通过Service来控制的,那么我的启动与隐藏就都扔给Service处理就OK。
- public void onClick(View v) {
 - switch(v.getId()) {
 - case R.id.btn_show:
 - Intent show = new Intent(this, FloatingWindowService.class);
 - show.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_SHOW);
 - startService(show);
 - break;
 - case R.id.btn_hide:
 - Intent hide = new Intent(this, FloatingWindowService.class);
 - hide.putExtra(FloatingWindowService.OPERATION, FloatingWindowService.OPERATION_HIDE);
 - startService(hide);
 - break;
 - }
 - }
 
在Service里的onStart方法中,只需要根据传过来的操作参数,对handler检查进行操作即可。
- @Override
 - public void onStart(Intent intent, int startId) {
 - super.onStart(intent, startId);
 - int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);
 - switch(operation) {
 - case OPERATION_SHOW:
 - mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
 - mHandler.sendEmptyMessage(HANDLE_CHECK_ACTIVITY);
 - break;
 - case OPERATION_HIDE:
 - mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
 - break;
 - }
 - }
 
另外:需要增加以下权限!!
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
 - <uses-permission android:name="android.permission.GET_TASKS"/>
 
                    
                
                
            
        
浙公网安备 33010602011771号