scroll_configuration.dart 4.05 KB
Newer Older
1
/// Copyright 2016 The Chromium Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:meta/meta.dart';
6
import 'package:flutter/foundation.dart';
7

8 9 10
import 'framework.dart';
import 'scroll_behavior.dart';

11 12 13
/// Controls how [Scrollable] widgets in a subtree behave.
///
/// Used by [ScrollConfiguration].
14 15 16
abstract class ScrollConfigurationDelegate {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
17 18
  const ScrollConfigurationDelegate();

19 20 21 22
  /// Returns the platform whose scroll physics should be approximated. See
  /// [ScrollBehavior.platform].
  TargetPlatform get platform;

23
  /// Returns the ScrollBehavior to be used by generic scrolling containers like
24 25
  /// [Block].
  ExtentScrollBehavior createScrollBehavior();
26 27 28 29 30

  /// Generic scrolling containers like [Block] will apply this function to the
  /// Scrollable they create. It can be used to add widgets that wrap the
  /// Scrollable, like scrollbars or overscroll indicators. By default the
  /// [scrollWidget] parameter is returned unchanged.
31
  Widget wrapScrollWidget(BuildContext context, Widget scrollWidget) => scrollWidget;
32

33 34 35
  /// Overrides should return true if this ScrollConfigurationDelegate differs
  /// from the provided old delegate in a way that requires rebuilding its
  /// scrolling container descendants.
Adam Barth's avatar
Adam Barth committed
36
  bool updateShouldNotify(@checked ScrollConfigurationDelegate old);
37 38 39 40 41 42 43 44 45 46 47 48
}

class _DefaultScrollConfigurationDelegate extends ScrollConfigurationDelegate {
  const _DefaultScrollConfigurationDelegate();

  @override
  TargetPlatform get platform => defaultTargetPlatform;

  @override
  ExtentScrollBehavior createScrollBehavior() => new OverscrollWhenScrollableBehavior(platform: platform);

  @override
49 50 51
  bool updateShouldNotify(ScrollConfigurationDelegate old) => false;
}

52
/// A widget that controls descendant [Scrollable] widgets.
53 54 55
///
/// Classes that create Scrollables are not required to depend on this
/// Widget. The following general purpose scrolling widgets do depend
56 57 58
/// on [ScrollConfiguration]: [Block], [LazyBlock], [ScrollableViewport],
/// [ScrollableList], [ScrollableLazyList]. The [Scrollable] base class uses
/// [ScrollConfiguration] to create its [ScrollBehavior].
59
class ScrollConfiguration extends InheritedWidget {
60 61 62 63 64
  /// Creates a widget that controls descendant [Scrollable] widgets.
  ///
  /// If the [delegate] argument is null, the scroll configuration for this
  /// subtree is controlled by the default implementation of
  /// [ScrollConfigurationDelegate].
65 66 67
  ScrollConfiguration({
    Key key,
    this.delegate,
68
    @required Widget child
69 70
  }) : super(key: key, child: child);

71
  static const ScrollConfigurationDelegate _defaultDelegate = const _DefaultScrollConfigurationDelegate();
72 73 74 75 76 77 78

  /// Defines the ScrollBehavior and scrollable wrapper for descendants.
  final ScrollConfigurationDelegate delegate;

  /// The delegate property of the closest instance of this class that encloses
  /// the given context.
  ///
79 80 81 82
  /// If no such instance exists, returns a default
  /// [ScrollConfigurationDelegate] that approximates the scrolling physics of
  /// the current platform (see [defaultTargetPlatform]) using a
  /// [OverscrollWhenScrollableBehavior] behavior model.
83 84 85 86 87 88
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// ScrollConfigurationDelegate scrollConfiguration = ScrollConfiguration.of(context);
  /// ```
89 90 91 92 93 94 95
  static ScrollConfigurationDelegate of(BuildContext context) {
    ScrollConfiguration configuration = context.inheritFromWidgetOfExactType(ScrollConfiguration);
    return configuration?.delegate ?? _defaultDelegate;
  }

  /// A utility function that calls [ScrollConfigurationDelegate.wrapScrollWidget].
  static Widget wrap(BuildContext context, Widget scrollWidget) {
96
    return ScrollConfiguration.of(context).wrapScrollWidget(context, scrollWidget);
97 98 99 100 101 102 103
  }

  @override
  bool updateShouldNotify(ScrollConfiguration old) {
    return delegate?.updateShouldNotify(old.delegate) ?? false;
  }
}