Android 如何在方向更改后使全屏覆盖保持全屏?

Android 如何在方向更改后使全屏覆盖保持全屏?,android,android-layout,android-service,android-view,android-fullscreen,Android,Android Layout,Android Service,Android View,Android Fullscreen,我正在制作一个应用程序,它可以在你的屏幕上创建小精灵动画 我有一个主要活动,有一个按钮“启动服务”。这将启动一个服务,该服务(在onCreate()中)创建一个全屏视图并将其附加到根窗口管理器 这部分工作得很好。它充满了屏幕,你可以离开应用程序,动画仍然可以在任何地方看到 旋转设备时会出现问题 精灵已经移到屏幕中间,但这是一个无关的问题;这里最重要的是黑暗的边界框-这个框显示了我可以画的画布,它需要填充整个屏幕 视图仍然是纵向模式,即使所有其他布局似乎已正确更新 部分问题来自于我如何指定视

我正在制作一个应用程序,它可以在你的屏幕上创建小精灵动画

我有一个主要活动,有一个按钮“启动服务”。这将启动一个服务,该服务(在
onCreate()
中)创建一个全屏视图并将其附加到根窗口管理器

这部分工作得很好。它充满了屏幕,你可以离开应用程序,动画仍然可以在任何地方看到

旋转设备时会出现问题

精灵已经移到屏幕中间,但这是一个无关的问题;这里最重要的是黑暗的边界框-这个框显示了我可以画的画布,它需要填充整个屏幕

视图仍然是纵向模式,即使所有其他布局似乎已正确更新


部分问题来自于我如何指定视图的维度。我使用标志来指定“全屏”,但这并没有设置视图的
宽度
高度
,以匹配屏幕的尺寸。因此,我必须在启动时手动设置

我不知道创建视图后如何更新视图的宽度和高度,但我觉得我需要这样做,因为视图的尺寸决定画布的尺寸

我的服务创建如下视图:

公共类WalkerService扩展服务{
私人WalkerView视图;
@凌驾
public void onCreate(){
super.onCreate();
最终WindowManager wm=(WindowManager)getSystemService(窗口服务);
最终DisplayMetrics=新的DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
view=newwalkerview(this);//扩展SurfaceView
final WindowManager.LayoutParams params=新建WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_全屏显示,
WindowManager.LayoutParams.FLAG_全屏显示,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,//apiLevel>=19中的TYPE_SYSTEM_警报被拒绝
WindowManager.LayoutParams.FLAG_布局在屏幕中,
像素格式。半透明
);
view.setFitsSystemWindows(false);//允许我们在状态栏、导航栏上绘制
//这里我手动设置尺寸,否则它默认为正方形(类似1024x1024)
params.width=metrics.widthPixels;
params.height=metrics.height像素;
wm.addView(视图,参数);
}
}
我尝试了倾听方向的变化,并在发生变化时旋转视图:

@覆盖
公共无效OnConfiguration已更改(配置newConfig){
super.onConfigurationChanged(newConfig);
view.setRotation(
newConfig.orientation==Configuration.orientation\u
?90.0f
:0.0f
);
}
但是
setRotation()
似乎并没有影响我视图的
宽度和
高度,也没有改变画布渲染的角度


我根本上误解了如何创建全屏覆盖吗?我如何保持在整个屏幕上画图的能力,而不考虑方向(甚至当我的应用程序不是活动应用程序时)

也许这与我将视图附加到窗口服务的窗口管理器这一事实有关——也许这意味着我的视图有一个奇怪的父视图(我可以想象,根视图可能不受方向的影响,或者没有定义的边界供子视图拉伸填充)

完整的源代码,以防我在这里遗漏了任何有用的信息


WalkerView.java
可能特别相关,因此。

我认为您的情况可以用另一种方法解决

  • 创建全屏自定义视图(您可以在自定义视图的构造函数中设置适当的标志)
  • 在自定义视图中重写
    onSizeChanged()
    。这将为您提供画布的高度和宽度。这是可选的。如果要使用半透明颜色填充整个自定义视图,则不需要这样做
  • 从上方使用宽度和高度,或者在自定义视图的
    onDraw()
    中使用
    canvas.drawColor()

  • 这将确保每当重新创建视图时,视图都会被重新绘制以填充整个屏幕(画布)。

    我被前面问题的答案误导了。也许它适用于较旧的API级别?我使用的是API级别24

    该具体答复建议:

    final WindowManager.LayoutParams params=new WindowManager.LayoutParams(
    WindowManager.LayoutParams.FLAG_全屏显示,
    WindowManager.LayoutParams.FLAG_全屏显示,
    WindowManager.LayoutParams.TYPE\系统\警报,
    WindowManager.LayoutParams.FLAG_布局在屏幕中,
    像素格式。半透明
    );
    
    这有一个问题。WindowManager.LayoutParams的构造函数如下所示:

    因此,
    WindowManager.LayoutParams.FLAG_全屏
    标志被用作
    int w
    int h
    的显式值。这不好


    我发现全屏覆盖的正确结构如下:

    final WindowManager.LayoutParams params=new WindowManager.LayoutParams(
    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,//apiLevel>=19中的TYPE_SYSTEM_警报被拒绝
    WindowManager.LayoutParams.FLAG_布局_在| WindowManager.LayoutParams.FLAG_全屏显示,
    像素格式。半透明
    );
    
    这意味着我们不再明确指定宽度和高度。布局完全依赖于我们的旗帜

    是,
    WindowManager.LayoutParams.FLAG\u LAYOUT\u IN\u SCREEN
    仍然是必需的标志;如果你想提取12月份的存款,这是必要的