如何检查我的小部件屏幕何时在像 Android 中的 onResume 这样的颤动中可见

Sp4*_*4Rx 32 android flutter

在android中,如果活动可见,onResume则调用。什么是相当于方法onResume颤振

我需要知道我的小部件屏幕何时可见,以便我可以根据它自动播放视频。我可能会转到另一个小部件屏幕,当我回来时它应该会自动播放。

我的方法是播放视频,didUpdateWidgetdidUpdateWidget每次即使小部件屏幕不可见也会被调用。

注意:我不是在问didChangeAppLifecycleStatefromWidgetsBindingObserver因为它为onResume应用程序生命周期提供等回调而不是特定的小部件屏幕。

Ami*_*mit 20

所有的问题都解决了。

从小部件树(materialappwidget)的根部开始在导航器上放置一个观察者。

如果您需要更多解释,请点击此链接:https : //api.flutter.dev/flutter/widgets/RouteObserver-class.html

我已经在我的项目中实现了它的伟大@Sp4Rx

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

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

class RouteAwareWidget extends StatefulWidget {
  State<RouteAwareWidget> createState() => RouteAwareWidgetState();
}

// Implement RouteAware in a widget's state and subscribe it to
// the
// RouteObserver.
class RouteAwareWidgetState extends State<RouteAwareWidget> with RouteAware {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

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

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

  @override
  void didPopNext() {
    // Covering route was popped off the navigator.
  }

  @override
  Widget build(BuildContext context) => Container();
}
Run Code Online (Sandbox Code Playgroud)

  • 在 `routeObserver.subscribe(this, ModalRoute.of(context));` 中,`ModalRoute.of(context)` 结果为 `参数类型 'ModalRoute&lt;Object?&gt;?' 无法分配给参数类型“PageRoute&lt;dynamic&gt;”。` (2认同)

ipc*_*cjs 8

因为后台路线的动画会被禁用。所以我们可以这样判断是否在前台:

final isForeground = TickerMode.of(context);
Run Code Online (Sandbox Code Playgroud)

将其包装到一个小部件中:

/// Created by ipcjs on 2021/3/23.
class ForegroundDetector extends StatefulWidget {
  const ForegroundDetector({
    Key? key,
    required this.child,
    required this.onForegroundChanged,
  }) : super(key: key);

  final ValueChanged<bool> onForegroundChanged;
  final Widget child;

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

class ForegroundDetectorState 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;
  }
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*tro 7

在不查看我的应用程序的主屏幕时,我很难让视频暂停。我应用了这个VisibilityDetector并抓住了visiblePercentage强制暂停或恢复:

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

      if (visiblePercentage < 1){ //the magic is done here
        if(_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)),


  @override
  void dispose() {
    // If the video is playing, pause it.
    _video_controller .pause();
    _video_controller .dispose();
    disposed_vid = true;
    super.dispose();
  }
Run Code Online (Sandbox Code Playgroud)


Kyl*_*enn 7

这些现有的问题都没有准确地回答我的问题,所以我在这里写了一个更彻底的答案,其中讨论了如何获得与 iOS 和 Android相同的生命周期方法。

但要点是:我建议使用FocusDetector包。它的工作原理与 onResume 和 onPause 完全相同。其实施方式如下。

class PageState extends State<Page> {

  void onResume() {
    log("onResume / viewWillAppear / onFocusGained");
  }

  void onPause() {
    log("onPause / viewWillDisappear / onFocusLost");
  }

  @override
  Widget build(BuildContext context) {
    return FocusDetector(
      onFocusGained: onResume,
      onFocusLost: onPause,
      child: Text('Rest of my widget'),
      );
  }
}
Run Code Online (Sandbox Code Playgroud)