tmo*_*use 21 android window android-layout android-activity
我希望能够创建一个始终位于Android显示屏前面的Activity.它应该不会收到任何输入,只需将其传递给下面的任何应用程序.像HUD一样的东西.
我能够研究我需要将底层窗口类型设置为TYPE_SYSTEM_ALERT,但看起来Android忽略了我的代码 - 即使我从清单中删除了android.permission.SYSTEM_ALERT_WINDOW权限也没有异常抛出.(需要使用此窗口类型).当我尝试在对话框上使用ALERT类型时,它工作正常,但我无法将对话框设置为全屏透明实体.这是我的代码,也许有一些简单的遗漏.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.main);
}
Run Code Online (Sandbox Code Playgroud)
必须在xml清单中外部启用半透明设置,否则它也不起作用.
<item name="android:windowIsTranslucent">true</item>
Run Code Online (Sandbox Code Playgroud)
tmo*_*use 24
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
ViewGroup mTopView = (ViewGroup) App.inflater.inflate(R.layout.main, null);
getWindow().setAttributes(params);
wm.addView(mTopView, params);
Run Code Online (Sandbox Code Playgroud)
我发现接受的答案(由 tmouse 提供)对我来说不太适用。也许它适用于较旧的 API 级别?我正在使用 API 级别 24。
该特定答案建议:
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
);
Run Code Online (Sandbox Code Playgroud)
这有问题。存在的构造函数WindowManager.LayoutParams如下:
因此该WindowManager.LayoutParams.FLAG_FULLSCREEN标志被用作and的显式值int wint h。这不好!你的视图尺寸被设置为 1024*1024——所以它不会填满屏幕。即使您明确设置布局的宽度和高度以匹配设备的尺寸:当屏幕方向改变时,它们也不会更新。我们需要一种不同的方法……
我发现全屏覆盖的正确构造是这样的:
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, // TYPE_SYSTEM_ALERT is denied in apiLevel >=19
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT
);
Run Code Online (Sandbox Code Playgroud)
这意味着我们不再明确指定宽度和高度。布局完全依赖于我们的标志。
是的,WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN仍然是必需的标志;如果要绘制状态栏等装饰,则有必要。
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY应该TYPE_SYSTEM_ALERT在 API 级别 >=19 中使用而不是使用。这是我不久前写的一个便条,遗憾的是我一直无法找到引文来证实我为什么这么认为,所以请加一点盐。
附注(如果您正在阅读本文,您可能正在尝试制作全屏叠加):
您的清单将需要这些权限(此处说明):
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Run Code Online (Sandbox Code Playgroud)
我的理解是这SYSTEM_ALERT_WINDOW是所需的实际权限,但这ACTION_MANAGE_OVERLAY_PERMISSION也是必需的:它允许您在运行时请求用户授予SYSTEM_ALERT_WINDOW权限。
我在这里提供了我的工作 API 级别 24 应用程序的源代码,该应用程序创建了一个全屏覆盖。