visibility_detector

v0.4.0+2

A widget that detects the visibility of its child and notifies a callback.

Package archive: https://pubdev.letsnova.ru/api/archives/visibility_detector/0.4.0+2.tar.gz

Installdart pub add visibility_detector

Readme

VisibilityDetector

A VisibilityDetector widget wraps an existing Flutter widget and fires a callback when the widget's visibility changes. (It actually reports when the visibility of the VisibilityDetector itself changes, and its visibility is expected to be identical to that of its child.)

Callbacks are not fired immediately on visibility changes. Instead, callbacks are deferred and coalesced such that the callback for each VisibilityDetector will be invoked at most once per VisibilityDetectorController.updateInterval (unless forced by VisibilityDetectorController.notifyNow()). Callbacks for all VisibilityDetector widgets are fired together synchronously between frames.

VisibilityDetectorController.notifyNow() may be used to force triggering pending visibility callbacks; this might be desirable just prior to tearing down the widget tree (such as when switching views or when exiting the application).

For more details, see the documentation to the VisibilityDetector, VisibilityInfo, and VisibilityDetectorController classes.

Example usage

@override
                Widget build(BuildContext context) {
                  return VisibilityDetector(
                    key: Key('my-widget-key'),
                    onVisibilityChanged: (visibilityInfo) {
                      var visiblePercentage = visibilityInfo.visibleFraction * 100;
                      debugPrint(
                          'Widget ${visibilityInfo.key} is ${visiblePercentage}% visible');
                    },
                    child: someOtherWidget,
                  );
                }
                

See the example/ directory for a sample application. To build it, first create the default Flutter project files:

cd example
                flutter create .
                

and then it can be run with flutter run.

Widget tests

Widget tests that use VisibilityDetectors usually should set:

VisibilityDetectorController.instance.updateInterval = Duration.zero;
                

This will have two effects:

  1. Visibility changes will be reported immediately, which can be less surprising for automated tests.

  2. It avoids the following assertion when tearing down the widget tree:

    The following assertion was thrown running a test:
    A Timer is still pending even after the widget tree was disposed.

    See https://github.com/flutter/flutter/issues/24166 for details.

If setting updateInterval = Duration.zero is undesirable, to address each of the corresponding issues above, tests alternatively can:

  1. Wait sufficiently long for callbacks to fire:

    await tester.pump(VisibilityDetectorController.instance.updateInterval);
                    
  2. Avoid the "Timer is still pending..." assertion by explicitly destroying the widget tree before the test completes:

    await tester.pumpWidget(Placeholder());
                    

See test/widget_test.dart for examples.

Known limitations

  • VisibilityDetector considers only its bounding box. It does not take widget opacity into account.

  • The reported visibleFraction might not account for overlapping widgets that obscure the VisbilityDetector.

Changelog

CHANGELOG

0.4.0+2

  • Fix a bug for updates to render objects that have not been laid out yet.

0.4.0+1

  • Correct Flutter SDK version dependency to 3.1.0.
  • Replace use of deprecated APIs in the example for compatibility with Flutter v3.1.0.

0.4.0

  • Refactor to avoid forcing composition in the layer/render trees.
  • Remove VisibilityDetectorLayer.
  • Add RenderVisibilityDetectorBase as a mixin that mostly takes over functionality from the old layer.
  • Remove the lookup map/method for getting former screen rects and instead add the rect to VisibilityInfo.

0.3.3

  • Re-apply Flutter framework bindings' null safety calls but set SDK constraints correctly to 2.12.0 instead.

0.3.2

  • Reverts change from 0.3.0 where the Flutter version constraint should have been set to 2.12.0 instead of 2.10.5.

0.3.1-dev

  • Populate the pubspec repository field.

0.3.0

  • Move to Flutter version 2.10.5 and update dependencies' null safety calls.

0.2.2

  • Minor internal changes to maintain forward-compatibility with flutter#91753.

0.2.1

  • Bug fix for using VisibilityDetector with FittedBox and Transform.scale issue #285.

0.2.0

  • Added SliverVisibilityDetector to report visibility of RenderSliver-based widgets. Fixes issue #174.

0.2.0-nullsafety.1

  • Revert change to add VisibilityDetectorController.scheduleNotification, which introduced unexpected memory usage.

0.2.0-nullsafety.0

  • Update to null safety.

  • Try to fix the link to the example on pub.dev.

  • Revert tests to again use RenderView instead of TestWindow.

  • Add VisibilityDetectorController.scheduleNotification to force firing a visibility callback.

0.1.5

  • Compatibility fixes to demo.dart for Flutter 1.13.8.

  • Moved demo.dart to an examples/ directory, renamed it, and added instructions to README.md.

  • Adjusted tests to use TestWindow instead of RenderView.

  • Added a "Known limitations" section to README.md.

0.1.4

  • Style and comment adjustments.

  • Fix a potential infinite loop in the demo app and add tests for it.

0.1.3

  • Fixed positioning of text selection handles for EditableText-based widgets (e.g. TextField, CupertinoTextField) when used within a VisibilityDetector.

  • Added VisibilityDetectorController.widgetBoundsFor.

0.1.2

  • Compatibility fixes for Flutter 1.3.0.

0.1.1

  • Added VisibilityDetectorController.forget.