| /// Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/rendering.dart'; |
| |
| import 'framework.dart'; |
| import 'overscroll_indicator.dart'; |
| import 'scroll_physics.dart'; |
| |
| const Color _kDefaultGlowColor = const Color(0xFFFFFFFF); |
| |
| /// Describes how [Scrollable] widgets should behave. |
| /// |
| /// Used by [ScrollConfiguration] to configure the [Scrollable] widgets in a |
| /// subtree. |
| @immutable |
| class ScrollBehavior { |
| /// Creates a description of how [Scrollable] widgets should behave. |
| const ScrollBehavior(); |
| |
| /// The platform whose scroll physics should be implemented. |
| /// |
| /// Defaults to the current platform. |
| TargetPlatform getPlatform(BuildContext context) => defaultTargetPlatform; |
| |
| /// Wraps the given widget, which scrolls in the given [AxisDirection]. |
| /// |
| /// For example, on Android, this method wraps the given widget with a |
| /// [GlowingOverscrollIndicator] to provide visual feedback when the user |
| /// overscrolls. |
| Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) { |
| // When modifying this function, consider modifying the implementation in |
| // _MaterialScrollBehavior as well. |
| switch (getPlatform(context)) { |
| case TargetPlatform.iOS: |
| return child; |
| case TargetPlatform.android: |
| case TargetPlatform.fuchsia: |
| return new GlowingOverscrollIndicator( |
| child: child, |
| axisDirection: axisDirection, |
| color: _kDefaultGlowColor, |
| ); |
| } |
| return null; |
| } |
| |
| /// The scroll physics to use for the platform given by [getPlatform]. |
| /// |
| /// Defaults to [BouncingScrollPhysics] on iOS and [ClampingScrollPhysics] on |
| /// Android. |
| ScrollPhysics getScrollPhysics(BuildContext context) { |
| switch (getPlatform(context)) { |
| case TargetPlatform.iOS: |
| return const BouncingScrollPhysics(); |
| case TargetPlatform.android: |
| case TargetPlatform.fuchsia: |
| return const ClampingScrollPhysics(); |
| } |
| return null; |
| } |
| |
| /// Called whenever a [ScrollConfiguration] is rebuilt with a new |
| /// [ScrollBehavior] of the same [runtimeType]. |
| /// |
| /// If the new instance represents different information than the old |
| /// instance, then the method should return true, otherwise it should return |
| /// false. |
| /// |
| /// If this method returns true, all the widgets that inherit from the |
| /// [ScrollConfiguration] will rebuild using the new [ScrollBehavior]. If this |
| /// method returns false, the rebuilds might be optimized away. |
| bool shouldNotify(covariant ScrollBehavior oldDelegate) => false; |
| |
| @override |
| String toString() => '$runtimeType'; |
| } |
| |
| /// Controls how [Scrollable] widgets behave in a subtree. |
| /// |
| /// The scroll configuration determines the [ScrollPhysics] and viewport |
| /// decorations used by descendants of [child]. |
| class ScrollConfiguration extends InheritedWidget { |
| /// Creates a widget that controls how [Scrollable] widgets behave in a subtree. |
| /// |
| /// The [behavior] and [child] arguments must not be null. |
| const ScrollConfiguration({ |
| Key key, |
| @required this.behavior, |
| @required Widget child, |
| }) : super(key: key, child: child); |
| |
| /// How [Scrollable] widgets that are descendants of [child] should behave. |
| final ScrollBehavior behavior; |
| |
| /// The [ScrollBehavior] for [Scrollable] widgets in the given [BuildContext]. |
| /// |
| /// If no [ScrollConfiguration] widget is in scope of the given `context`, |
| /// a default [ScrollBehavior] instance is returned. |
| static ScrollBehavior of(BuildContext context) { |
| final ScrollConfiguration configuration = context.inheritFromWidgetOfExactType(ScrollConfiguration); |
| return configuration?.behavior ?? const ScrollBehavior(); |
| } |
| |
| @override |
| bool updateShouldNotify(ScrollConfiguration oldWidget) { |
| assert(behavior != null); |
| return behavior.runtimeType != oldWidget.behavior.runtimeType |
| || (behavior != oldWidget.behavior && behavior.shouldNotify(oldWidget.behavior)); |
| } |
| |
| @override |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| super.debugFillProperties(properties); |
| properties.add(new DiagnosticsProperty<ScrollBehavior>('behavior', behavior)); |
| } |
| } |