How to make flutter app draw behind android navigation bar and make navigation bar fully transparent?
FlutterDartUinavigationbarFlutter LayoutTransparentFlutter Problem Overview
I would like to make my Flutter app take up the entire screen in Android while still showing both the status bar and the navigation bar, with both of them transparent, to achieve the full screen look like in iOS.
The status bar color can be easily changed, but right now I'm facing problems with getting the app to fill up the screen and making the navigation bar transparent at the same time.
By default, the app is not drawn below the navigation bar at all (I've set the status bar color to be transparent):
https://i.imgur.com/RWh57zUl.png"><img src="https://i.imgur.com/RWh57zUl.png" width="300" alt="default app without modifications">
Here are some solutions I've tried:
1) Setting flags on window in the onCreate function in MainActivity
Solution taken from here: https://stackoverflow.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)
}
This sort of achieves what I want, but it has several problems. The padding and inset values in MediaQuery
are now 0, so I have to manually get the status bar and nav bar heights through the use of MethodChannel
. Furthermore, this creates a weird bug regarding the application switcher, as shown below (see how the content jumps and the debug banner on the top right is stretched):
https://i.imgur.com/DIGIIht.gif"><img src="https://i.imgur.com/DIGIIht.gif" width="300" alt="solution 1 bug">
2) Adding translucent navigation in styles.xml
<item name="android:windowTranslucentNavigation">true</item>
Result:
https://i.imgur.com/VMEp9Zj.png"><img src="https://i.imgur.com/VMEp9Zj.png" width="300" alt="solution 2 result">
This is the closest to what I want to achieve. MediaQuery.of(context).padding.top
correctly shows the top padding, and MediaQuery.of(context).viewInsets.bottom
correctly shows the height of the navbar. There are no weird bugs in the application switcher as well. The only problem is that the navbar is translucent and not transparent.
Here's the repo for the sample app shown above: https://github.com/CZX123/navbar
It would be nice if Flutter could provide this functionality out of the box. But it doesn't, so are there any other better ways to achieve this?
Update
It seems like we would have to wait for the Flutter team to officially implement this feature:
https://github.com/flutter/flutter/issues/40974
https://github.com/flutter/flutter/issues/34678
This comment also perfectly sums up the current behavior in Android: https://github.com/flutter/flutter/issues/34678#issuecomment-536028077
Flutter Solutions
Solution 1 - Flutter
After Flutter 2.5.0:
This works for me like charm!
Inside your main()
paste the code below:
//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]);
Solution 2 - Flutter
I achieved the transparency effect throughout my app easily by editing the following files
1.Add the following lines in 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.Add the following in your 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
}
}
3. Remove SystemChrome.setSystemUIOverlayStyle commands from your main.dart
- Run
flutter clean
and re run your app.
NOTE:
-
In case you nest a stack direct under the scaffold for some screen, you might see your app drawing above nav bar. To fix that just set the following property on scaffold
resizeToAvoidBottomInset: false
-
If you use an appbar or safeArea you might need to override the SystemUIOverlayStyle again using AnnotatedRegion
Solution 3 - Flutter
The following worked for me:
build.gradle (app)
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());
}
Inspiration came from https://github.com/flutter/flutter/issues/40974
Solution 4 - Flutter
So if you are using Flutter the procedure is:
- Set
AppBar()
color to transparent. - Set
extendBeyondAppBar
totrue
. - Set
elevation
to 0.
As an example:
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
)
Solution 5 - Flutter
Though I don't know, which side effects this approach might cause, I believe it offers a solution to your question:
Scaffold(
primary: false,
appBar: AppBar(
primary: false,
// ...
),
// ...
)
Setting both the Scaffold's and the AppBar's primary property to false
removes their inner SafeArea, which renders them behind system UI.
Solution 6 - Flutter
If it's still an issue, here's a solution:
Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea()
)
backgroundColor parameter specifies the background of the whole app. If you put nothing inside the scaffold's body - the whole app will be just a black screen with a status bar. If you do put some widgets inside the body - the status bar will still be colored as if you're not inside an app.
Solution 7 - Flutter
return Scaffold(
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarColor: Colors.transparent
),
sized: false,
child: Container(color: Colors.red)
)
);
Solution 8 - Flutter
This might be late, but the latest version for flutter, 1.12 provides a feature to draw the app behind the NavigationBar, so the following code will have the transparent navigation bar with app fully extended behind the navigation bar,
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,
),
);
Solution 9 - Flutter
Have you tried the below method
// to hide only bottom bar:
SystemChrome.setEnabledSystemUIOverlays ([SystemUiOverlay.top]);
// to hide only status bar:
SystemChrome.setEnabledSystemUIOverlays ([SystemUiOverlay.bottom]);
// to hide both:
SystemChrome.setEnabledSystemUIOverlays ([]);