问题背景
在全面屏手机到来的时代,Android手机有虚拟按键导航和全面屏手势。
应用市场要求APP适配Android12,当我们的app设计时需要采用沉浸式的布局。 在没有设置SplashScreen时,能够正确的自然沉浸到StatusBar上。 但当使用了SplashScreen,参考文章《向应用添加闪屏页》
情况一
如果采用下列的初始化方式
import android.os.Build
import android.os.Bundle
import androidx.core.view.WindowCompat
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Aligns the Flutter view vertically with the window.
WindowCompat.setDecorFitsSystemWindows(getWindow(), false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Disable the Android splash screen fade out animation to avoid
// a flicker before the similar frame is drawn in Flutter.
splashScreen.setOnExitAnimationListener { splashScreenView -> splashScreenView.remove() }
}
super.onCreate(savedInstanceState)
}
}
就会发现显示出了默认的ActionBar。
解决办法
style.xml中修改Theme.App.Starting
<!--增加下面两行-->
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
运行后效果如下图
情况二
如果启动动画需要自定义Activity做交互动画。需要运行
val splashScreen: SplashScreen = this.installSplashScreen()
来获取自定义时。情况会更加复杂。
就会发现StatusBar和NavigationBar没有沉浸。
解决办法
第一步
style.xml的修改
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!--下面三个是关键属性-->
<item name="android:windowLightNavigationBar">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:enforceNavigationBarContrast">false</item>
</style>
修改了style.xml后发现,在Pixal的模拟器上,发现底部导航栏的颜色会随着后面的背景色自动切换深浅模式。但是在vivo,oppo,华为等手机在虚拟按键的模式上并不能自动切换深浅模式,需要手动的处理。
第二步
main.dart中设置SystemUiOverlayStyle
SystemUiOverlayStyle light = SystemUiOverlayStyle.dark.copyWith(
systemNavigationBarIconBrightness: Brightness.dark,
//使用的时候发现,在虚拟按键的手机上,如果是采用全透明颜色,虚拟按键上将会有个半透明的白色覆盖,达不到全屏沉浸效果,所以需要使用非0透明值的颜色。
systemNavigationBarColor: Colors.white.withOpacity(0.1),
systemNavigationBarContrastEnforced: true,
statusBarColor: Colors.transparent);
void main() {
runApp(const MyApp());
SystemChrome.setSystemUIOverlayStyle(light);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(light);
return MaterialApp(
title: 'Demo',
theme: ThemeData(
useMaterial3: true,
primarySwatch: Colors.blue,
appBarTheme: AppBarTheme(
//AppBar会覆盖主题,建议和SystemChrome.setSystemUIOverlayStyle是同一style
systemOverlayStyle: light,
),
),
home: const HomePage());
}
}
当使用的是二段式或者三段式虚拟导航键,在代码中systemNavigationBarColor: Colors.white.withOpacity(0.1),如果这里使用纯透明的颜色,navigationBarColor将会被设置成白色的半透明。
如果对app有要求,可以把颜色设置为0.1alpha的白色
Android8以下的兼容问题。
在Android 8的模拟器上,虚拟栏是这样的。
情况一如下图。
情况二如下图:
情况一设置了对应的style更换NavigationBarColor也没有效果,所以需要兼容Android 8以下的APP推荐使用情况二。