Hide top status bar after bringing it back

Viewed 1422

The issue is after hiding it when I bring it back by top swiping it then stays...

How do I solve this? Maybe some kind of listener on touching the top status bar??

enter image description here

My code

class _MyProfileState extends State<MyProfile> {
  @override
  void initState() {
    SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
    super.initState();
  }

  @override
  void dispose() {
    SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My Profile'),
        elevation: 0,
      ),
      body: Container(),
    );
  }
}
6 Answers

Listen to the system UI change callback and restore the previously set system UI overlay after a set duration.

The duration must be at least one second since android restricts changing system UI to once every second (for malware reasons).

Put the below code in main or any method that you are sure would run once.

SystemChrome.setSystemUIChangeCallback((systemOverlaysAreVisible) async {
  await Future.delayed(const Duration(seconds: 1));
  SystemChrome.restoreSystemUIOverlays();
});

Make sure widget bindings are initialized before running this code.

WidgetsFlutterBinding.ensureInitialized();

I tested a lot but didn't achieve any good solution. But my temporary solution is to use a timer to verify page full-screen every one second.

The final code is like below:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ProfilePage extends StatefulWidget {
  const ProfilePage({Key? key}) : super(key: key);

  @override
  _ProfilePageState createState() => _ProfilePageState();
}

class _ProfilePageState extends State<ProfilePage> {
  late Timer _timer;

  @override
  void initState() {
    _setSystemUIOverlays();
    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      _setSystemUIOverlays();
    });
    super.initState();
  }

  void _setSystemUIOverlays() {
    SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
  }

  @override
  void dispose() {
    _timer.cancel();
    SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Profile Page"),
      ),
      body: Center(
        child: Text('FullScreen'),
      ),
    );
  }
}

Just add the mixin WidgetsBindingObserver to your state and override the method didChangeMetrics like below:

class _MyProfileState extends State<MyProfile>  with WidgetsBindingObserver{

  @override
  void initState() {
    super.initState();
    SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
    WidgetsBinding.instance!.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance!.removeObserver(this);
    super.dispose();
  }

  @override void didChangeMetrics() {
     SystemChrome.restoreSystemUIOverlays();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My Profile'),
        elevation: 0,
      ),
      body: Container(),
    );
  }
}

The easiest ways I found to implement these were:

To remove status and navigation bars use:

SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays:[]);

To bring them back (make them visible) use:

SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);

Try this:

 class _MyProfileState extends State<MyProfile> {
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
       SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
        return Scaffold(
          appBar: AppBar(
            title: Text('My Profile'),
            elevation: 0,
          ),
          body: Container(),
        );
      }
    }

I think you can use the Listener widget. https://api.flutter.dev/flutter/widgets/Listener-class.html

And you probably want to use these specific callbacks:

  • onPointerUp
  • onPointerMove
  • onPointerDown

I think their names are pretty self-explanatory. You can visit the official docs I linked above for more info.

Here's an example code

class ProfilePage extends StatelessWidget {
  const ProfilePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Listener(
        /* When the user interacts in your app body like click, move etc. */
        onPointerUp: hideStatusBar,
        onPointerMove: hideStatusBar,
        onPointerDown: hideStatusBar,
        /* When the user interacts in your app body like click, move etc. */
        child: Container(
          child: SizedBox(),
        ),
      ),
    );
  }
}

void hideStatusBar(PointerEvent details) {
  SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
}

What will happen here is that the user will still be able to view the status bar but when they click or interact with your app page body, the status bar will be hidden again. Just explore more pointer callbacks if something doesn't work.

Related