通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得 WindowManager对象。
使用WindowManager可以在其他应用最上层,甚至手机桌面最上层显示窗口。
调用的是WindowManager继承自基类的addView方法和removeView方法来显示和隐藏窗口。
type值
用于确定悬浮窗的类型,一般设为2002,表示在所有应用程序之上,但在状态栏之下。
flags值
用于确定悬浮窗的行为,比如说不可聚焦,非模态对话框等等,属性非常多,大家可以查看文档。
gravity值
用于确定悬浮窗的对齐方式,一般设为左上角对齐,这样当拖动悬浮窗的时候方便计算坐标。
x值
用于确定悬浮窗的位置,如果要横向移动悬浮窗,就需要改变这个值。
y值
用于确定悬浮窗的位置,如果要纵向移动悬浮窗,就需要改变这个值。
width值
用于指定悬浮窗的宽度。
height值
用于指定悬浮窗的高度。
WindowManager实现悬浮窗
声明权限
AndroidManifest.xml中添加如下代码
注意:
Android 6.0以上【非系统应用】,需要在[系统设置]找到[应用和通知]已经的[我们的应用],然后点击进入[高级],打开[在应用上方显示]开关
demo代码片段
MainActivity.java
public class WindowActivity extends Activity {
private String TAG = getClass().getSimpleName();
private WindowManager windowManager;
private WindowManager.LayoutParams mLayoutParams = null;
private View seekbarLayoutView = null;
private boolean hasWindow = false;
private LayoutInflater inflater = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate : ");
setContentView(R.layout.activity_main);
initUI();
initWindow();
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume: ");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause: ");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
private void initUI() {
findViewById(R.id.main_bt_one).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick show(): ");
show();
}
});
return;
}
private void initWindow() {
inflater = LayoutInflater.from(getApplicationContext());
windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mLayoutParams = new WindowManager.LayoutParams();
//设置透明度
mLayoutParams.alpha = 1.0f;
//Android 6.0后,非系统应用,需要在[系统设置]找到[应用和通知]已经的[我们的应用],然后点击进入[高级],打开[在应用上方显示]开关
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//6.0 以上
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN;
mLayoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
mLayoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
seekbarLayoutView = inflater.inflate(R.layout.topbar_layout, null);
seekbarLayoutView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick hide(): ");
hide();
}
});
return;
}
private void show() {
Log.d(TAG, "show hasWindow : " + hasWindow);
if (null != windowManager && (null != seekbarLayoutView) &&
(seekbarLayoutView.getParent() == null) && !hasWindow) {
hasWindow = true;
windowManager.addView(seekbarLayoutView, mLayoutParams);
}
return;
}
private void hide() {
Log.d(TAG, "hide hasWindow : " + hasWindow);
if (null != windowManager && (null != seekbarLayoutView) && hasWindow) {
windowManager.removeView(seekbarLayoutView);
hasWindow = false;
}
return;
}
activity_main.xml
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@android:color/darker_gray"
android:orientation="vertical">
android:id="@+id/main_bt_one"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center"
android:text="one" />
topbar_layout.xml
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_green_dark"
android:paddingTop="160dp"
tools:ignore="MissingDefaultResource">
参考文档