mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
122 lines
4.3 KiB
Dart
122 lines
4.3 KiB
Dart
// Copyright 2014 The Flutter 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 = 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:
|
|
case TargetPlatform.macOS:
|
|
return child;
|
|
case TargetPlatform.android:
|
|
case TargetPlatform.fuchsia:
|
|
return 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:
|
|
case TargetPlatform.macOS:
|
|
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() => objectRuntimeType(this, 'ScrollBehavior');
|
|
}
|
|
|
|
/// 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.dependOnInheritedWidgetOfExactType<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(DiagnosticsProperty<ScrollBehavior>('behavior', behavior));
|
|
}
|
|
}
|