LCOV - code coverage report
Current view: top level - lists - stacked_scroll_view.dart (source / functions) Hit Total Coverage
Test: filtered.info Lines: 37 37 100.0 %
Date: 2022-01-21 22:05:42 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/gestures.dart';
       2             : import 'package:flutter/material.dart';
       3             : 
       4             : /// {@template stacked_scroll_view}
       5             : /// A widget that displays a scrollable view behind another widget.
       6             : ///
       7             : /// This widget is typically used to display a search bar at the top or a button
       8             : /// at the bottom of a scrollable view. The scrollable [backgroundChild] will
       9             : /// have padding applied to it so that the content of the scrollable view will
      10             : /// be offset properly to account for [foregroundChild].
      11             : ///
      12             : /// For example, if [alignToTop] is `true`, the [foregroundChild] will be placed
      13             : /// at the top and the scrollable [backgroundChild] will have padding applied to
      14             : /// the top to account for the size of the [foregroundChild].
      15             : /// {@endtemplate}
      16             : class StackedScrollView extends StatefulWidget {
      17             :   /// {@macro stacked_scroll_view}
      18           1 :   const StackedScrollView({
      19             :     Key? key,
      20             :     this.alignToTop = true,
      21             :     this.scrollDirection = Axis.vertical,
      22             :     this.reverse = false,
      23             :     this.padding,
      24             :     this.primary,
      25             :     this.physics,
      26             :     this.controller,
      27             :     this.dragStartBehavior = DragStartBehavior.start,
      28             :     this.clipBehavior = Clip.hardEdge,
      29             :     this.restorationId,
      30             :     this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
      31             :     required this.foregroundChild,
      32             :     required this.backgroundChild,
      33           1 :   }) : super(key: key);
      34             : 
      35             :   /// Whether to align the [foregroundChild] to the top of the scrollable view.
      36             :   ///
      37             :   /// If `true`, the [foregroundChild] and the padding necessary to account for
      38             :   /// it will be placed at the top of the scrollable view. Otherwise, they will
      39             :   /// be placed at the bottom.
      40             :   final bool alignToTop;
      41             : 
      42             :   /// The direction in which this widget scrolls.
      43             :   final Axis scrollDirection;
      44             : 
      45             :   /// Whether the scroll view scrolls in the reading direction.
      46             :   final bool reverse;
      47             : 
      48             :   /// The amount of space by which to inset the [foregroundChild].
      49             :   final EdgeInsets? padding;
      50             : 
      51             :   /// Whether this is the primary scroll view associated with the parent
      52             :   final bool? primary;
      53             : 
      54             :   /// How the scroll view should respond to user input.
      55             :   final ScrollPhysics? physics;
      56             : 
      57             :   /// The controller that manages the scroll view.
      58             :   final ScrollController? controller;
      59             : 
      60             :   /// {@macro flutter.widgets.scrollable.dragStartBehavior}
      61             :   final DragStartBehavior dragStartBehavior;
      62             : 
      63             :   /// The clipping behavior to use.
      64             :   final Clip clipBehavior;
      65             : 
      66             :   /// {@macro flutter.widgets.scrollable.restorationId}
      67             :   final String? restorationId;
      68             : 
      69             :   /// How this scroll view should dismiss the on-screen keyboard.
      70             :   final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
      71             : 
      72             :   /// The widget to show in front of the [backgroundChild].
      73             :   ///
      74             :   /// Depending on [alignToTop], this widget will either be placed at the top
      75             :   /// or the bottom of the viewport. The height of this widget will determine
      76             :   /// how much padding is applied to the appropriate side of the scrollable
      77             :   /// [backgroundChild].
      78             :   final Widget foregroundChild;
      79             : 
      80             :   /// The scrollable widget to show behind the [foregroundChild].
      81             :   ///
      82             :   /// This widget will have padding applied to it so that the content of the
      83             :   /// scrollable view will be offset properly to account for the size of the
      84             :   /// [foregroundChild]. Where this padding is applied is determined by
      85             :   /// [alignToTop].
      86             :   final Widget backgroundChild;
      87             : 
      88           1 :   @override
      89           1 :   State<StackedScrollView> createState() => _StackedScrollViewState();
      90             : }
      91             : 
      92             : class _StackedScrollViewState extends State<StackedScrollView> {
      93             :   final _foregroundKey = GlobalKey();
      94             : 
      95             :   var _foregroundHeight = 0.0;
      96             : 
      97           1 :   @override
      98             :   void initState() {
      99           1 :     super.initState();
     100           1 :     _scheduleForegroundHeightUpdate();
     101             :   }
     102             : 
     103           1 :   void _scheduleForegroundHeightUpdate() {
     104           3 :     WidgetsBinding.instance!.addPostFrameCallback((_) {
     105           2 :       setState(() {
     106           5 :         _foregroundHeight = _foregroundKey.currentContext!.size!.height;
     107             :       });
     108             :     });
     109             :   }
     110             : 
     111           1 :   @override
     112             :   Widget build(BuildContext context) {
     113           1 :     final foregroundInsets = EdgeInsets.only(
     114           3 :       top: widget.alignToTop ? _foregroundHeight : 0.0,
     115           3 :       bottom: widget.alignToTop ? 0.0 : _foregroundHeight,
     116             :     );
     117             :     final effectivePadding =
     118           3 :         (widget.padding ?? EdgeInsets.zero).add(foregroundInsets);
     119             : 
     120           1 :     return NotificationListener<SizeChangedLayoutNotification>(
     121           1 :       onNotification: (notification) {
     122           1 :         _scheduleForegroundHeightUpdate();
     123             :         return true;
     124             :       },
     125           1 :       child: Stack(
     126           1 :         children: <Widget>[
     127           1 :           SingleChildScrollView(
     128           2 :             scrollDirection: widget.scrollDirection,
     129           2 :             reverse: widget.reverse,
     130             :             padding: effectivePadding,
     131           2 :             primary: widget.primary,
     132           2 :             physics: widget.physics,
     133           2 :             controller: widget.controller,
     134           2 :             dragStartBehavior: widget.dragStartBehavior,
     135           2 :             clipBehavior: widget.clipBehavior,
     136           2 :             restorationId: widget.restorationId,
     137           2 :             keyboardDismissBehavior: widget.keyboardDismissBehavior,
     138           2 :             child: widget.backgroundChild,
     139             :           ),
     140           1 :           Align(
     141           2 :             alignment: widget.alignToTop
     142             :                 ? Alignment.topCenter
     143             :                 : Alignment.bottomCenter,
     144           1 :             child: SizeChangedLayoutNotifier(
     145           1 :               key: _foregroundKey,
     146           2 :               child: widget.foregroundChild,
     147             :             ),
     148             :           )
     149             :         ],
     150             :       ),
     151             :     );
     152             :   }
     153             : }

Generated by: LCOV version 1.15