WindowManager主要用来管理窗口的一些状态、屏幕分辨率、属性、view增加、删除、更新、窗口顺序、消息收集和处理等。其继承于ViewManager,获取这个对象有两种方式:

1、Activity.getWindowManager();

2、(WindowManager)Context.getSystemService(Context.Window_SERVICE);

其中有主要用到3个方法:

1、添加窗口

public void addView(View view, ViewGroup.LayoutParams params);

2、删除窗口

public void removeView(View view);

3、更新窗口

public void updateViewLayout(View view, ViewGroup.LayoutParams params);

还可以利用WindowManager获取屏幕的分辨率:

// 屏幕的宽度
		wManager = contextActivity.getWindowManager();
		DisplayMetrics dm = new DisplayMetrics();
		wManager.getDefaultDisplay().getMetrics(dm);
		//屏幕宽度
		screenWith = dm.widthPixels;
		//屏幕高度
		screenheigt=dm.heightPixels;



其内部有一个静态类,windowManager.LayoutParams,这个类可以设置窗口的各种属性,下面对这个类做一下介绍。

继承关系 :
java.lang.Object
   ↳android.view.ViewGroup.LayoutParams
       ↳android.view.WindowManager.LayoutParams

各种属性:

1.public int x; 如果忽略gravity属性,那么它表示窗口的绝对X位置。   什么是gravity属性呢?简单地说,就是窗口如何停靠。  当设置了 Gravity.LEFT 或 Gravity.RIGHT 之后,x值就表示到特定边的距离。

2. public int y; 如果忽略gravity属性,那么它表示窗口的绝对Y位置。 当设置了 Gravity.TOP 或 Gravity.BOTTOM 之后,y值就表示到特定边的距离。

3. public float horizontalWeight; public float verticalWeight; 在纵/横向上,为关联的view预留了多少扩展空间(像素)。如果是0,那么此view不能被拉伸。

   其他情况下,扩展空间(像素)将被widget所均分。


4.public int type;


窗口类型。有3种主要类型:


Applicationwindows:


        取值在 FIRST_APPLICATION_WINDOW 和 LAST_APPLICATION_WINDOW 之间。

是通常的、顶层的应用程序窗口。必须将 token 设置成 activity 的 token 。


Sub_windows:


        取值在 FIRST_SUB_WINDOW 和 LAST_SUB_WINDOW 之间。

 与顶层窗口相关联,token 必须设置为它所附着的宿主窗口的 token。


Systemwindows:


        取值在 FIRST_SYSTEM_WINDOW 和 LAST_SYSTEM_WINDOW 之间。

用于特定的系统功能。它不能用于应用程序,使用时需要特殊权限。


 


下面定义了 type 的取值:


      应用程序窗口。

      public static final int FIRST_APPLICATION_WINDOW = 1;

      所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。     

      public static final int TYPE_BASE_APPLICATION   =1;       

      普通应哟功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。

      public static final int TYPE_APPLICATION       = 2;

       用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。

      它用于让系统显示些信息,直到应用程序可以开启自己的窗口。   

      public static final int TYPE_APPLICATION_STARTING = 3;   

     应用程序窗口结束。

      public static final int LAST_APPLICATION_WINDOW = 99;

      子窗口。子窗口的Z序和坐标空间都依赖于他们的宿主窗口。

      public static final int FIRST_SUB_WINDOW       = 1000;

      面板窗口,显示于宿主窗口上层。

      public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;

      媒体窗口,例如视频。显示于宿主窗口下层。

      public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;

      应用程序窗口的子面板。显示于所有面板窗口的上层。(GUI的一般规律,越“子”越靠上)

      public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW +2;

      对话框。类似于面板窗口,绘制类似于顶层窗口,而不是宿主的子窗口。

      public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW +3;

      媒体信息。显示在媒体层和程序窗口之间,需要实现透明(半透明)效果。(例如显示字幕)

      public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW +4;

      子窗口结束。( End of types of sub-windows )

      public static final int LAST_SUB_WINDOW        = 1999;

      系统窗口。非应用程序创建。

     public static final int FIRST_SYSTEM_WINDOW    = 2000;

      状态栏。只能有一个状态栏;它位于屏幕顶端,其他窗口都位于它下方。

     public static final int TYPE_STATUS_BAR        =  FIRST_SYSTEM_WINDOW;

      搜索栏。只能有一个搜索栏;它位于屏幕上方。

      public static final int TYPE_SEARCH_BAR        = FIRST_SYSTEM_WINDOW+1;

      电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。

      public static final int TYPE_PHONE            = FIRST_SYSTEM_WINDOW+2;

      系统提示。它总是出现在应用程序窗口之上。

      public static final int TYPE_SYSTEM_ALERT      =  FIRST_SYSTEM_WINDOW +3;

      锁屏窗口。

      public static final int TYPE_KEYGUARD          = FIRST_SYSTEM_WINDOW +4;

      信息窗口。用于显示toast。

      public static final int TYPE_TOAST            = FIRST_SYSTEM_WINDOW +5;

      系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。

      public static final int TYPE_SYSTEM_OVERLAY    =  FIRST_SYSTEM_WINDOW +6;

      电话优先,当锁屏时显示。此窗口不能获得输入焦点,否则影响锁屏。

      public static final int TYPE_PRIORITY_PHONE    =  FIRST_SYSTEM_WINDOW +7;

      系统对话框。(例如音量调节框)。

      public static final int TYPE_SYSTEM_DIALOG     =  FIRST_SYSTEM_WINDOW +8;

      锁屏时显示的对话框。

      public static final int TYPE_KEYGUARD_DIALOG   =  FIRST_SYSTEM_WINDOW +9;

      系统内部错误提示,显示于所有内容之上。

      public static final int TYPE_SYSTEM_ERROR      =  FIRST_SYSTEM_WINDOW +10;

      内部输入法窗口,显示于普通UI之上。应用程序可重新布局以免被此窗口覆盖。

      public static final int TYPE_INPUT_METHOD      =  FIRST_SYSTEM_WINDOW +11;

      内部输入法对话框,显示于当前输入法窗口之上。

      public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW +12;

      墙纸窗口。 public static final int TYPE_WALLPAPER         = FIRST_SYSTEM_WINDOW +13;

      状态栏的滑动面板。 public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW +14;

      系统窗口结束。 public static final int LAST_SYSTEM_WINDOW     = 2999;






在工作中做一款游戏SDK,里面有一个效果就是有一个悬浮按钮浮在游戏上面,点击可以弹出一个框,在框里有两个按钮,点击按钮可以进入对应的条目,这个我就是用的windowmanager实现的,先来上个效果图:


Android viewgroup 悬浮模式 android windowmanager悬浮_应用程序

给这个类的代码贴一下吧,源码就不给了,~~~~~~~~~


public class FloatingViewController {

	private Button bbsBtn, hideBtn;

	private TextView bbsTV, hideTV;

	private LinearLayout containerLayout;

	private WindowManager.LayoutParams wmParams;

	private WindowManager.LayoutParams wmcParams;

	private WindowManager wManager;

	// 当前手指所在屏幕中的坐标
	private float xInScreen;

	private float yInScreen;
	private float xScreen;

	private float yScreen;
	private int loacation[] = new int[] { 0, 0 };

	// 窗口中的位置的坐标

	private float xInView;

	private float yInView;

	private Button circleButton;

	private int screenWidth = 0;

	private static float screenScale = 0;

	private int statusBarHeight;

	private int viewLength = 0;
	private int screenWith;
	private SharedPreferences locationPreferences;
	private static int count;

	private static Activity contextActivity;

	private FloatingViewController() {
	}

	private static FloatingViewController fvc;

	public static FloatingViewController getInstance(Activity context) {
		count++;
		contextActivity = context;
		if (fvc == null) {
			fvc = new FloatingViewController();
		}
		return fvc;
	}

	public void show() {
		if (count > 1) {
			return;
		}
		wManager = contextActivity.getWindowManager();
		Display display = wManager.getDefaultDisplay();
		screenWith = display.getWidth();
		wmParams = new WindowManager.LayoutParams();
		wmParams.format = PixelFormat.RGBA_8888;
		wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
		wmParams.gravity = Gravity.LEFT | Gravity.TOP;
		wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
		circleButton = new Button(contextActivity);
		screenWidth = new SizeUtils(contextActivity).sysWidth;

		if (screenScale == 0) {
			if (new SizeUtils(contextActivity).screenHeightScale < new SizeUtils(
					contextActivity).screenWidthScale)
				screenScale = new SizeUtils(contextActivity).screenHeightScale;
			else {
				screenScale = new SizeUtils(contextActivity).screenWidthScale;
			}
		}
		viewLength = (int) (235 * screenScale);
		circleButton.setBackgroundDrawable(contextActivity.getResources()
				.getDrawable(
						MResource.getIdByName(contextActivity, "drawable",
								"overlay_logo")));
		circleButton.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:

					xInView = event.getX();
					yInView = event.getY();
					xScreen = event.getRawX();
					yScreen = event.getRawY() - getStatusBarHeight();
					Log.e("按下", xScreen + "按下" + yScreen);
					break;
				case MotionEvent.ACTION_MOVE:
					if (containerLayout != null)
						containerLayout.setVisibility(View.INVISIBLE);
					xInScreen = event.getRawX();
					yInScreen = event.getRawY() - getStatusBarHeight();
					updateViewPosition();
					Log.e("移动", "移动");
					break;
				case MotionEvent.ACTION_UP:
					Log.e("触摸弹起", xInScreen + "触摸弹起" + yInScreen);
					xInScreen = event.getRawX();
					yInScreen = event.getRawY() - getStatusBarHeight();
					if (xInScreen <= screenWith / 2) {// 图标icon吸附在左边
						wmParams.x = 0;
					} else {// 图标icon吸附在右边
						wmParams.x = screenWith;
					}
					if (Math.abs(xInScreen - xScreen) < 5
							&& Math.abs(yInScreen - yScreen) < 5) {
						circleButton.getLocationOnScreen(loacation);
						int viewRight = screenWidth
								- (wmParams.x + wmParams.width / 2);
						int viewLeft = wmParams.x;
						if (viewLeft > viewLength && containerLayout == null) {
							openLeftBigWindow();
						} else if (viewRight > viewLength
								&& containerLayout == null) {
							openRightBigWindow();
						} else
							removeBigWindow();

					}

					wManager.updateViewLayout(circleButton, wmParams);
					Editor editor = locationPreferences.edit();
					editor.putFloat("x", (int) xInScreen);
					editor.putFloat("y", (int) yInScreen);
					editor.commit();

				}
				return false;
			}
		});

		wmParams.width = wmParams.height = (int) (60 * screenScale);

		locationPreferences = contextActivity
				.getPreferences(android.content.Context.MODE_PRIVATE);

		xInScreen = locationPreferences.getFloat("x", new SizeUtils(
				contextActivity).sysWidth);
		yInScreen = locationPreferences.getFloat("y", new SizeUtils(
				contextActivity).sysHeight / 2);
		xInView = 60;
		yInView = 60;
		wmParams.x = 0;
		wmParams.y = (int) yInScreen;
		wManager.addView(circleButton, wmParams);
		// updateViewPosition();

	}

	private void updateViewPosition() {
		wmParams.x = (int) (xInScreen - xInView);
		wmParams.y = (int) (yInScreen - yInView);
		wManager.updateViewLayout(circleButton, wmParams);
		Editor editor = locationPreferences.edit();
		editor.putFloat("x", (int) xInScreen);
		editor.putFloat("y", (int) yInScreen);
		editor.commit();
	}

	protected void openLeftBigWindow() {

		if (wmcParams == null) {

			wmcParams = new WindowManager.LayoutParams();
			wmcParams.format = PixelFormat.RGBA_8888;
			wmcParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;

			wmcParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			wmcParams.gravity = Gravity.LEFT | Gravity.TOP;
			wmcParams.x = (int) (loacation[0] - viewLength);
			wmcParams.y = (int) (wmParams.y);

			wmcParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
			wmcParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

			containerLayout = new LinearLayout(contextActivity);
			containerLayout.setBackgroundResource(MResource.getIdByName(
					contextActivity, "drawable", "overlay_lift"));
			bbsTV = new TextView(contextActivity);
			bbsTV.setText("账户");
			bbsTV.setTextColor(Color.WHITE);

			hideTV = new TextView(contextActivity);
			hideTV.setText("隐藏");
			hideTV.setTextColor(Color.WHITE);

			hideBtn = new Button(contextActivity);
			hideBtn.setBackgroundResource(MResource.getIdByName(
					contextActivity, "drawable", "overlay_hide"));
			hideBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					AnimationSet set = new AnimationSet(true);
					set.addAnimation(new ScaleAnimation(1f, 1.5f, 1f, 1.5f));
					set.setDuration(300);
					set.setInterpolator(new AnticipateOvershootInterpolator(9F));
					count = 0;
					hideBtn.startAnimation(set);
					hideTV.startAnimation(set);
					removeAllWindow();
				}
			});

			bbsBtn = new Button(contextActivity);
			bbsBtn.setBackgroundResource(MResource.getIdByName(contextActivity,
					"drawable", "overlay_account"));
			bbsBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					AnimationSet set = new AnimationSet(true);
					set.addAnimation(new ScaleAnimation(1f, 1.2f, 1f, 1.2f));
					set.setDuration(300);
					set.setInterpolator(new AnticipateOvershootInterpolator(9f));
					set.setInterpolator(new BounceInterpolator());
					bbsBtn.startAnimation(set);
					bbsTV.startAnimation(set);
					if (containerLayout != null)
						containerLayout.setVisibility(View.INVISIBLE);
					Intent intent = new Intent(contextActivity,
							AccountActivity.class);
					contextActivity.startActivity(intent);

				}
			});

			containerLayout.setLayoutParams(new LinearLayout.LayoutParams(256,
					60));
			containerLayout.setPadding(10, 10, 10, 10);
			containerLayout.setGravity(Gravity.CENTER_VERTICAL);

			LinearLayout.LayoutParams bbsLayoutParams = new LinearLayout.LayoutParams(
					40, 40);
			bbsLayoutParams.setMargins(0, 0, 0, 0);

			// LayoutParams homeParams = new LinearLayout.LayoutParams(60, 60);
			LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.WRAP_CONTENT,
					LinearLayout.LayoutParams.WRAP_CONTENT);
			textParams.setMargins(10, 0, 0, 0);

			LinearLayout.LayoutParams hideTextLayoutParams = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.WRAP_CONTENT,
					LinearLayout.LayoutParams.WRAP_CONTENT);
			hideTextLayoutParams.setMargins(10, 0, 0, 0);

			LinearLayout.LayoutParams hideLayoutParams = new LinearLayout.LayoutParams(
					40, 40);
			hideLayoutParams.setMargins(20, 0, 0, 0);

			bbsBtn.setLayoutParams(bbsLayoutParams);
			hideBtn.setLayoutParams(hideLayoutParams);
			bbsTV.setLayoutParams(textParams);
			hideTV.setLayoutParams(hideTextLayoutParams);

			containerLayout.addView(bbsBtn);
			containerLayout.addView(bbsTV);
			containerLayout.addView(hideBtn);
			containerLayout.addView(hideTV);
			RelayoutViewTool
					.relayoutViewWithScale(containerLayout, screenScale);

			wManager.addView(containerLayout, wmcParams);

		} else {

			removeBigWindow();
		}

	}

	protected void openRightBigWindow() {

		if (wmcParams == null) {
			wmcParams = new WindowManager.LayoutParams();
			wmcParams.format = PixelFormat.RGBA_8888;
			wmcParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
			wmcParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			wmcParams.gravity = Gravity.LEFT | Gravity.TOP;
			Log.e("test", wmcParams.width + "--wmcparm");
			wmcParams.x = (int) (loacation[0] + wmParams.width);
			wmcParams.y = (int) (wmParams.y);
			Log.e("wmcParams", wmParams.x + "vs" + wmParams.y + "("
					+ wmcParams.x + "--" + wmcParams.y + ")");
			wmcParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
			wmcParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

			containerLayout = new LinearLayout(contextActivity);
			containerLayout.setBackgroundResource(MResource.getIdByName(
					contextActivity, "drawable", "overlay_right"));
			bbsTV = new TextView(contextActivity);
			bbsTV.setText("账户");
			bbsTV.setTextColor(Color.WHITE);

			hideTV = new TextView(contextActivity);
			hideTV.setText("隐藏");
			hideTV.setTextColor(Color.WHITE);

			hideBtn = new Button(contextActivity);
			hideBtn.setBackgroundResource(MResource.getIdByName(
					contextActivity, "drawable", "overlay_hide"));
			hideBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					AnimationSet set = new AnimationSet(true);
					set.addAnimation(new ScaleAnimation(1f, 1.5f, 1f, 1.5f));
					set.setDuration(300);
					set.setInterpolator(new AnticipateOvershootInterpolator(9F));
					// set.setInterpolator(new BounceInterpolator());
					hideBtn.startAnimation(set);
					hideTV.startAnimation(set);
					count = 0;
					removeAllWindow();
				}
			});

			bbsBtn = new Button(contextActivity);
			bbsBtn.setBackgroundResource(MResource.getIdByName(contextActivity,
					"drawable", "overlay_account"));
			bbsBtn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					AnimationSet set = new AnimationSet(true);
					set.addAnimation(new ScaleAnimation(1f, 1.2f, 1f, 1.2f));
					set.setDuration(300);
					set.setInterpolator(new AnticipateOvershootInterpolator(9f));
					set.setInterpolator(new BounceInterpolator());
					bbsBtn.startAnimation(set);
					bbsTV.startAnimation(set);
					if (containerLayout != null)
						containerLayout.setVisibility(View.INVISIBLE);
					Intent intent = new Intent(contextActivity,
							AccountActivity.class);
					contextActivity.startActivity(intent);

				}
			});

			containerLayout.setLayoutParams(new LinearLayout.LayoutParams(256,
					60));
			containerLayout.setPadding(10, 10, 10, 10);
			containerLayout.setGravity(Gravity.CENTER_VERTICAL);

			LinearLayout.LayoutParams bbsLayoutParams = new LinearLayout.LayoutParams(
					40, 40);
			bbsLayoutParams.setMargins(20, 0, 0, 0);

			// LayoutParams homeParams = new LinearLayout.LayoutParams(60, 60);
			LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.WRAP_CONTENT,
					LinearLayout.LayoutParams.WRAP_CONTENT);
			textParams.setMargins(10, 0, 0, 0);

			LinearLayout.LayoutParams hideTextLayoutParams = new LinearLayout.LayoutParams(
					LinearLayout.LayoutParams.WRAP_CONTENT,
					LinearLayout.LayoutParams.WRAP_CONTENT);
			hideTextLayoutParams.setMargins(10, 0, 0, 0);

			LinearLayout.LayoutParams hideLayoutParams = new LinearLayout.LayoutParams(
					40, 40);
			hideLayoutParams.setMargins(20, 0, 0, 0);

			bbsBtn.setLayoutParams(bbsLayoutParams);
			hideBtn.setLayoutParams(hideLayoutParams);
			bbsTV.setLayoutParams(textParams);
			hideTV.setLayoutParams(hideTextLayoutParams);

			containerLayout.addView(bbsBtn);
			containerLayout.addView(bbsTV);
			containerLayout.addView(hideBtn);
			containerLayout.addView(hideTV);
			RelayoutViewTool
					.relayoutViewWithScale(containerLayout, screenScale);

			wManager.addView(containerLayout, wmcParams);
		} else {
			removeBigWindow();
		}

	}

	protected void removeBigWindow() {

		if (containerLayout != null && wmcParams != null) {
			wManager.removeView(containerLayout);
			containerLayout = null;
			wmcParams = null;
		}
		// if(containerLayout==null){
		// wManager.removeView(containerLayout);
		//
		// }

	}

	public void removeAllWindow() {

		removeBigWindow();
		wManager.removeView(circleButton);
		circleButton = null;
		wManager = null;
		fvc = null;

	}

	private int getStatusBarHeight() {

		if (statusBarHeight == 0) {

			try {
				@SuppressWarnings("rawtypes")
				Class c = Class.forName("com.android.internal.R$dimen");

				try {
					Object o = c.newInstance();

					try {
						Field field = c.getField("status_bar_height");
						int x = field.getInt(o);
						statusBarHeight = contextActivity.getResources()
								.getDimensionPixelSize(x);
					} catch (NoSuchFieldException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return statusBarHeight;
	}

	public void destroyFloat() {

		if (containerLayout != null) {
			count=0;
			removeAllWindow();
		}
		
//		if (containerLayout == null&&circleButton != null) {
//			wManager.removeView(circleButton);
//			circleButton = null;
//			wManager = null;
//			fvc = null;
//		}
		
	
		if (fvc != null) {
			count = 0;
			removeAllWindow();
		}

	}

}