在 Android 版本 >= 5 上绘制导航栏(和其他应用程序)
Draw over navigation bar (and other apps) on Android version >= 5
我想在服务的其他应用程序的屏幕上绘制一个(鼠标指针)图标。我已经实现了功能,除了导航栏之外,我可以在屏幕上绘制。我在这里研究了 several other questions 并尝试了 TYPE_SYSTEM_OVERLAY
、TYPE_TOAST
、TYPE_SYSTEM_ERROR
和其他一些 window 类型但没有成功。
我不是要捕捉焦点,只是在屏幕上画鼠标指针一两秒钟。当我尝试在导航栏上绘制时,它只是在下方(实际上,RelativeLayout 在导航栏的边框上结束 - 即使我为高度指定了手动尺寸)。下面的屏幕截图显示了屏幕右下方的手形指针。这是我能定位的最低点。请注意,我并没有试图在我的应用程序中隐藏导航栏 - 试图覆盖其他应用程序。
我什至尝试在 WindowManager.LayoutParams
实例中设置 xpos
和 ypos
偏移设置,但这只是偏移了布局并且仍然位于导航栏下方)。
我用来展示这个的布局参数 window:
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSPARENT);
然后我将带有这些参数的 RelativeLayout
添加到 WindowManager:windowManager.addView(relativeLayout, params);
底部的导航栏不能被绘制,因为上面绘制的项目可能会妨碍访问主页按钮、后退按钮等。但是你可以让你的 activity 全屏,这意味着它将隐藏导航按钮,直到您从底部向上滑动,这样您就可以在屏幕上的任何地方自由绘制
编辑:我发现了一些类似的问题,这个问题有答案:Draw bitmaps on top of the Navigation bar in Android
答案是添加一个与导航栏大小相同的 y 偏移量。
经过大量的摆弄,我设法获得了正确的标志以使其工作。它几乎可以工作(对于大多数应用程序)。实现的代码如下(按钮单击处理程序的示例):
@Override
public void onClick(View view) {
if (_windowManager == null) {
_windowManager = (WindowManager) MainActivity.this.getSystemService(Context.WINDOW_SERVICE);
}
WindowManager.LayoutParams params;
// create the view on the first try
if (_overlayView == null) {
ImageView hand;
_overlayView = new FrameLayout(MainActivity.this);
hand = new ImageView(MainActivity.this);
hand.setImageResource(R.drawable.icon_hand_pointer);
int w = hand.getDrawable().getIntrinsicWidth();
int h = hand.getDrawable().getIntrinsicHeight();
_overlayView.addView(hand);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
params.width = w;
params.height = h;
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = _xOffset;
params.y = _yOffset;
_windowManager.addView(_overlayView, params);
} else {
// move the view
params = (WindowManager.LayoutParams) _overlayView.getLayoutParams();
params.x = _xOffset;
params.y = _yOffset;
_windowManager.removeView(_overlayView);
_overlayView.setLayoutParams(params);
_windowManager.addView(_overlayView, params);
}
_xOffset += 40;
_yOffset += 100;
}
这是此代码在应用程序中运行的屏幕截图(您可以看到手形覆盖图;这是在 Android 6.0.1 的 Nexus 5 上:
我想在服务的其他应用程序的屏幕上绘制一个(鼠标指针)图标。我已经实现了功能,除了导航栏之外,我可以在屏幕上绘制。我在这里研究了 several other questions 并尝试了 TYPE_SYSTEM_OVERLAY
、TYPE_TOAST
、TYPE_SYSTEM_ERROR
和其他一些 window 类型但没有成功。
我不是要捕捉焦点,只是在屏幕上画鼠标指针一两秒钟。当我尝试在导航栏上绘制时,它只是在下方(实际上,RelativeLayout 在导航栏的边框上结束 - 即使我为高度指定了手动尺寸)。下面的屏幕截图显示了屏幕右下方的手形指针。这是我能定位的最低点。请注意,我并没有试图在我的应用程序中隐藏导航栏 - 试图覆盖其他应用程序。
我什至尝试在 WindowManager.LayoutParams
实例中设置 xpos
和 ypos
偏移设置,但这只是偏移了布局并且仍然位于导航栏下方)。
我用来展示这个的布局参数 window:
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSPARENT);
然后我将带有这些参数的 RelativeLayout
添加到 WindowManager:windowManager.addView(relativeLayout, params);
底部的导航栏不能被绘制,因为上面绘制的项目可能会妨碍访问主页按钮、后退按钮等。但是你可以让你的 activity 全屏,这意味着它将隐藏导航按钮,直到您从底部向上滑动,这样您就可以在屏幕上的任何地方自由绘制
编辑:我发现了一些类似的问题,这个问题有答案:Draw bitmaps on top of the Navigation bar in Android 答案是添加一个与导航栏大小相同的 y 偏移量。
经过大量的摆弄,我设法获得了正确的标志以使其工作。它几乎可以工作(对于大多数应用程序)。实现的代码如下(按钮单击处理程序的示例):
@Override
public void onClick(View view) {
if (_windowManager == null) {
_windowManager = (WindowManager) MainActivity.this.getSystemService(Context.WINDOW_SERVICE);
}
WindowManager.LayoutParams params;
// create the view on the first try
if (_overlayView == null) {
ImageView hand;
_overlayView = new FrameLayout(MainActivity.this);
hand = new ImageView(MainActivity.this);
hand.setImageResource(R.drawable.icon_hand_pointer);
int w = hand.getDrawable().getIntrinsicWidth();
int h = hand.getDrawable().getIntrinsicHeight();
_overlayView.addView(hand);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
params.width = w;
params.height = h;
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = _xOffset;
params.y = _yOffset;
_windowManager.addView(_overlayView, params);
} else {
// move the view
params = (WindowManager.LayoutParams) _overlayView.getLayoutParams();
params.x = _xOffset;
params.y = _yOffset;
_windowManager.removeView(_overlayView);
_overlayView.setLayoutParams(params);
_windowManager.addView(_overlayView, params);
}
_xOffset += 40;
_yOffset += 100;
}
这是此代码在应用程序中运行的屏幕截图(您可以看到手形覆盖图;这是在 Android 6.0.1 的 Nexus 5 上: