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实现的,先来上个效果图:
给这个类的代码贴一下吧,源码就不给了,~~~~~~~~~
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();
}
}
}