Skip to content Skip to sidebar Skip to footer

How To Check When My Widget Screen Comes To Visibility In Flutter Like Onresume In Android

In android if an activity is visible onResume is called. What is the equivalent method of onResume in Flutter? I need the know when my widget screen is visible so I can auto-pla

Solution 1:

All of the problems are solved.

Put an observer on the navigator from the root of the widget tree (materialappwidget).

If you need more explanation please follow this link: https://api.flutter.dev/flutter/widgets/RouteObserver-class.html

I have implemented in my project and its working great @Sp4Rx

// Register the RouteObserver as a navigation observer.
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

voidmain() {
  runApp(MaterialApp(
    home: Container(),
    navigatorObservers: [routeObserver],
  ));
}

classRouteAwareWidgetextendsStatefulWidget {
  State<RouteAwareWidget> createState() => RouteAwareWidgetState();
}

// Implement RouteAware in a widget's state and subscribe it to// the// RouteObserver.classRouteAwareWidgetStateextendsState<RouteAwareWidget> withRouteAware {
  @overridevoiddidChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @overridevoiddispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  @overridevoiddidPush() {
    // Route was pushed onto navigator and is now topmost route.
  }

  @overridevoiddidPopNext() {
    // Covering route was popped off the navigator.
  }

  @overrideWidgetbuild(BuildContext context) => Container();
}

Solution 2:

I struggled to get a video to pause when not viewing the main screen of my app. I applied this VisibilityDetector and grabbed the visiblePercentage to force a pause or resume:

VisibilityDetector(
    key: Key('visible-video--key-${this.randomkeygenerator}-1'),
    onVisibilityChanged: (visibilityInfo) {
      var visiblePercentage = visibilityInfo.visibleFraction * 100;

      if (visiblePercentage < 1){ //the magic is done hereif(_video_controller != null) {
          if(disposed_vid == false) {
            _video_controller.pause();
          }
        }

      }else{
        if(_video_controller != null) {
          if(disposed_vid == false) {
            _video_controller.play();
          }
        }
      }
      debugPrint(
          'Widget ${visibilityInfo.key} is ${visiblePercentage}% visible');
    },
    child: VideoPlayer(_video_controller)),


  @overridevoiddispose() {
    // If the video is playing, pause it.
    _video_controller .pause();
    _video_controller .dispose();
    disposed_vid = true;
    super.dispose();
  }

Solution 3:

Because the animation of the background route will be disabled. So we can judge whether it is in the foreground in this way:

final isForeground = TickerMode.of(context);

Wrap it into a widget:

/// Created by ipcjs on 2021/3/23.classForegroundDetector extends StatefulWidget {
  constForegroundDetector({
    Key? key,
    required this.child,
    required this.onForegroundChanged,
  }) : super(key: key);final ValueChanged<bool> onForegroundChanged;
  final Widget child;

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

classForegroundDetectorState extends State<ForegroundDetector> {
  bool get isForeground => _isForeground ?? false;
  bool? _isForeground;

  @override
  Widget build(BuildContext context){
    final isForeground = TickerMode.of(context);
    if (_isForeground != isForeground) {
      _isForeground = isForeground;
      widget.onForegroundChanged(isForeground);
    }
    return widget.child;
  }
}

Solution 4:

It's probably not the simplest and definitely not perfect, but a while back I implemented events like those with routes. Basically, EventRoute<T> is a drop-in replacement for MaterialPageRoute<T> that provides optional callbacks for when the Widget is created, pushed to the foreground, pushed to the background and when it gets popped off.

event_route.dart:

import'package:flutter/material.dart';

enumRouteState {
  none,
  created,
  foreground,
  background,
  destroyed
}

classEventRoute<T> extendsMaterialPageRoute<T> {
  BuildContext _context;
  RouteState _state;
  Function(BuildContext) _onCreateCallback;
  Function(BuildContext) _onForegroundCallback;
  Function(BuildContext) _onBackgroundCallback;
  Function(BuildContext) _onDestroyCallback;

  EventRoute(BuildContext context, {
    builder,
    RouteSettings settings,
    bool maintainState = true,
    bool fullscreenDialog = false,
    Function(BuildContext) onCreate,
    Function(BuildContext) onForeground,
    Function(BuildContext) onBackground,
    Function(BuildContext) onDestroy
  }):
        _context = context,
        _onCreateCallback = onCreate,
        _onForegroundCallback = onForeground,
        _onBackgroundCallback = onBackground,
        _onDestroyCallback = onDestroy,
        _state = RouteState.none,
        super(builder: builder, settings: settings, maintainState: maintainState, fullscreenDialog: fullscreenDialog);


  void get state => _state;

  @overridevoiddidChangeNext(Route nextRoute) {
    if (nextRoute == null) {
      _onForeground();
    } else {
      _onBackground();
    }
    super.didChangeNext(nextRoute);
  }

  @override
  bool didPop(T result) {
    _onDestroy();
    returnsuper.didPop(result);
  }

  @overridevoiddidPopNext(Route nextRoute) {
    _onForeground();
    super.didPopNext(nextRoute);
  }

  @overrideTickerFuturedidPush() {
    _onCreate();
    returnsuper.didPush();
  }

  @overridevoiddidReplace(Route oldRoute) {
    _onForeground();
    super.didReplace(oldRoute);
  }

  void_onCreate() {
    if (_state != RouteState.none || _onCreateCallback == null) {
      return;
    }
    _onCreateCallback(_context);
  }

  void_onForeground() {
    if (_state == RouteState.foreground) {
      return;
    }
    _state = RouteState.foreground;
    if (_onForegroundCallback != null) {
      _onForegroundCallback(_context);
    }
  }

  void_onBackground() {
    if (_state == RouteState.background) {
      return;
    }
    _state = RouteState.background;
    if (_onBackgroundCallback != null) {
      _onBackgroundCallback(_context);
    }
  }

  void_onDestroy() {
    if (_state == RouteState.destroyed || _onDestroyCallback == null) {
      return;
    }
    _onDestroyCallback(_context);
  }
}

And then to push your route you do:

Navigator.push(context, EventRoute(context, builder: (context) =>YourWidget(context),
      onCreate: (context) =>print('create'),
      onForeground: (context) =>print('foreground'),
      onBackground: (context) =>print('background'),
      onDestroy: (context) =>print('destroy')
));

The context is a little icky though...

Post a Comment for "How To Check When My Widget Screen Comes To Visibility In Flutter Like Onresume In Android"