如何让 Flutter 应用在 android 导航栏后面绘制并使导航栏完全透明?
Posted
技术标签:
【中文标题】如何让 Flutter 应用在 android 导航栏后面绘制并使导航栏完全透明?【英文标题】:How to make flutter app draw behind android navigation bar and make navigation bar fully transparent? 【发布时间】:2019-10-29 16:21:20 【问题描述】:我想让我的 Flutter 应用在 android 中占据整个屏幕,同时仍然显示状态栏和导航栏,并且它们都是透明的,以实现ios 中的全屏外观。
状态栏颜色可以轻松更改,但现在我遇到了让应用填满屏幕并同时使导航栏透明的问题。
默认情况下,应用根本不绘制在导航栏下方(我已将状态栏颜色设置为透明):
以下是我尝试过的一些解决方案:
1) 在MainActivity的onCreate函数中设置窗口的flags
从这里获取的解决方案:https://***.com/a/31596735
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
这种实现了我想要的,但它有几个问题。 MediaQuery
中的 padding 和 inset 值现在为 0,因此我必须通过使用 MethodChannel
手动获取状态栏和导航栏高度。此外,这会产生一个关于应用程序切换器的奇怪错误,如下所示(查看内容如何跳转和右上角的调试横幅被拉伸):
2) 在styles.xml中添加半透明导航
<item name="android:windowTranslucentNavigation">true</item>
结果:
这是最接近我想要实现的目标。 MediaQuery.of(context).padding.top
正确显示顶部填充,MediaQuery.of(context).viewInsets.bottom
正确显示导航栏的高度。应用程序切换器中也没有奇怪的错误。唯一的问题是导航栏是半透明的而不是透明的。
这是上面显示的示例应用程序的存储库:https://github.com/CZX123/navbar
如果 Flutter 能够开箱即用地提供此功能,那就太好了。但事实并非如此,那么还有其他更好的方法来实现这一点吗?
更新
看来我们得等 Flutter 团队正式实现这个功能了:https://github.com/flutter/flutter/issues/40974https://github.com/flutter/flutter/issues/34678
这条评论也完美总结了Android中的当前行为:https://github.com/flutter/flutter/issues/34678#issuecomment-536028077
【问题讨论】:
这能回答你的问题吗? Transparent bottom navigation bar in flutter 不,这不是关于这个的。这个问题是关于实际系统 UI 导航(如 Android Q 中介绍的)在 Flutter 中无法正确呈现。 有没有找到让系统导航栏透明的解决方案? 【参考方案1】:我通过编辑以下文件轻松实现了整个应用的透明效果
1.在android/app/build.gradle
中添加以下行dependencies
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0-beta01' //add this line
2.在您的 android/app/src/main/kotlin/com/
import androidx.core.view.WindowCompat //add this line
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity()
//add the following block of code
override fun onPostResume()
super.onPostResume()
WindowCompat.setDecorFitsSystemWindows(window, false)
window.navigationBarColor = 0 //for transparent nav bar
window.statusBarColor = 0 //for transparent status bar
从你的 main.dart 中删除 SystemChrome.setSystemUIOverlayStyle 命令
运行 flutter clean
并重新运行您的应用。
注意:
如果您在某些屏幕的脚手架下直接嵌套堆栈, 您可能会在导航栏上方看到您的应用程序绘图。解决刚刚设置的问题 脚手架上的以下属性
resizeToAvoidBottomInset: false
如果您使用 appbar 或 safeArea,您可能需要使用 AnnotatedRegion
再次覆盖 SystemUIOverlayStyle【讨论】:
【参考方案2】:Flutter 2.5.0之后:
这对我来说就像魅力一样!
在您的main()
中粘贴以下代码:
//Setting SysemUIOverlay
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemStatusBarContrastEnforced: true,
systemNavigationBarColor: Colors.transparent,
systemNavigationBarDividerColor: Colors.transparent,
systemNavigationBarIconBrightness: Brightness.dark,
statusBarIconBrightness: Brightness.dark)
);
//Setting SystmeUIMode
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge, overlays: [SystemUiOverlay.top]);
【讨论】:
【参考方案3】:虽然我不知道这种方法可能会导致哪些副作用,但我相信它可以解决您的问题:
Scaffold(
primary: false,
appBar: AppBar(
primary: false,
// ...
),
// ...
)
将 Scaffold 和 AppBar 的主要属性都设置为 false
会删除它们的内部 SafeArea,这会将它们呈现在系统 UI 后面。
【讨论】:
【参考方案4】:以下内容对我有用:
build.gradle(应用程序)
implementation 'androidx.core:core-ktx:1.5.0-rc01'
MainActivity.kt
class MainActivity: FlutterActivity()
override fun onPostResume()
super.onPostResume()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
WindowCompat.setDecorFitsSystemWindows(window, false)
window.navigationBarColor = 0
main.dart
void main()
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark.copyWith(
systemNavigationBarColor: Colors.transparent,
statusBarColor: Colors.transparent,
));
runApp(MyApp());
灵感来自https://github.com/flutter/flutter/issues/40974
【讨论】:
【参考方案5】:如果仍然存在问题,这里有一个解决方案:
Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea()
)
backgroundColor 参数指定整个应用的背景。如果你在脚手架的主体内没有任何东西 - 整个应用程序将只是一个带有状态栏的黑屏。如果您确实在正文中放置了一些小部件 - 状态栏仍然会被着色,就好像您不在应用程序中一样。
【讨论】:
【参考方案6】:因此,如果您使用的是 Flutter,则过程是:
-
将
AppBar()
颜色设置为透明。
将extendBeyondAppBar
设置为true
。
将elevation
设置为0。
举个例子:
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
)
【讨论】:
这与导航栏无关。 这不是正确的答案。这是关于现代 Android 行为,其中在应用程序上绘制了一个小手势导航栏。【参考方案7】:return Scaffold(
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarColor: Colors.transparent
),
sized: false,
child: Container(color: Colors.red)
)
);
【讨论】:
【参考方案8】:这可能有点晚,但是flutter的最新版本,1.12提供了在NavigationBar后面绘制应用程序的功能,所以下面的代码将透明导航栏与应用程序完全扩展在导航栏后面,
Scaffold(
extendBodyBehindAppBar: true, //this ensures that the body is drawn behind the navigation bar as well
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text('Transparent Bar'),
),
body: Container(
color: Colors.blue,
),
);
【讨论】:
仅适用于 AppBar,不延伸到系统导航后面【参考方案9】:你试过下面的方法吗
// to hide only bottom bar:
SystemChrome.setEnabledSystemUIOverlays ([SystemUiOverlay.top]);
// to hide only status bar:
SystemChrome.setEnabledSystemUIOverlays ([SystemUiOverlay.bottom]);
// to hide both:
SystemChrome.setEnabledSystemUIOverlays ([]);
【讨论】:
我不想隐藏应用栏,我想让它们的背景透明。以上是关于如何让 Flutter 应用在 android 导航栏后面绘制并使导航栏完全透明?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Flutter 让后台应用每天下午 2 点打开一个对话框?
有没有办法让颤动的 webview 使用 android 相机进行文件上传?如何在 webview_flutter 中打开文件选择器?
Android Flutter:手把手教你如何进行Android 与 Flutter的相互通信