mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Add maybeOf
for all the cases where of
returns nullable. (#114120)
This commit is contained in:
parent
b20b7d995b
commit
37b72342b0
@ -210,8 +210,8 @@ class _ExpansionPanelsDemoState extends State<ExpansionPanelsDemo> {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CollapsibleBody(
|
return CollapsibleBody(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16.0),
|
margin: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
onSave: () { Form.of(context)!.save(); close(); },
|
onSave: () { Form.of(context).save(); close(); },
|
||||||
onCancel: () { Form.of(context)!.reset(); close(); },
|
onCancel: () { Form.of(context).reset(); close(); },
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
@ -244,8 +244,8 @@ class _ExpansionPanelsDemoState extends State<ExpansionPanelsDemo> {
|
|||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CollapsibleBody(
|
return CollapsibleBody(
|
||||||
onSave: () { Form.of(context)!.save(); close(); },
|
onSave: () { Form.of(context).save(); close(); },
|
||||||
onCancel: () { Form.of(context)!.reset(); close(); },
|
onCancel: () { Form.of(context).reset(); close(); },
|
||||||
child: FormField<Location>(
|
child: FormField<Location>(
|
||||||
initialValue: item.value,
|
initialValue: item.value,
|
||||||
onSaved: (Location? result) { item.value = result; },
|
onSaved: (Location? result) { item.value = result; },
|
||||||
@ -298,8 +298,8 @@ class _ExpansionPanelsDemoState extends State<ExpansionPanelsDemo> {
|
|||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CollapsibleBody(
|
return CollapsibleBody(
|
||||||
onSave: () { Form.of(context)!.save(); close(); },
|
onSave: () { Form.of(context).save(); close(); },
|
||||||
onCancel: () { Form.of(context)!.reset(); close(); },
|
onCancel: () { Form.of(context).reset(); close(); },
|
||||||
child: FormField<double>(
|
child: FormField<double>(
|
||||||
initialValue: item.value,
|
initialValue: item.value,
|
||||||
onSaved: (double? value) { item.value = value; },
|
onSaved: (double? value) { item.value = value; },
|
||||||
|
@ -12,7 +12,7 @@ class _PageSelector extends StatelessWidget {
|
|||||||
final List<Icon>? icons;
|
final List<Icon>? icons;
|
||||||
|
|
||||||
void _handleArrowButtonPress(BuildContext context, int delta) {
|
void _handleArrowButtonPress(BuildContext context, int delta) {
|
||||||
final TabController controller = DefaultTabController.of(context)!;
|
final TabController controller = DefaultTabController.of(context);
|
||||||
if (!controller.indexIsChanging) {
|
if (!controller.indexIsChanging) {
|
||||||
controller.animateTo((controller.index + delta).clamp(0, icons!.length - 1));
|
controller.animateTo((controller.index + delta).clamp(0, icons!.length - 1));
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ class _PageSelector extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final TabController? controller = DefaultTabController.of(context);
|
final TabController? controller = DefaultTabController.maybeOf(context);
|
||||||
final Color color = Theme.of(context).colorScheme.secondary;
|
final Color color = Theme.of(context).colorScheme.secondary;
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
|
@ -63,7 +63,7 @@ class TabbedComponentDemoScaffold extends StatefulWidget {
|
|||||||
|
|
||||||
class _TabbedComponentDemoScaffoldState extends State<TabbedComponentDemoScaffold> {
|
class _TabbedComponentDemoScaffoldState extends State<TabbedComponentDemoScaffold> {
|
||||||
void _showExampleCode(BuildContext context) {
|
void _showExampleCode(BuildContext context) {
|
||||||
final String? tag = widget.demos![DefaultTabController.of(context)!.index].exampleCodeTag;
|
final String? tag = widget.demos![DefaultTabController.of(context).index].exampleCodeTag;
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
Navigator.push(context, MaterialPageRoute<FullScreenCodeDialog>(
|
Navigator.push(context, MaterialPageRoute<FullScreenCodeDialog>(
|
||||||
builder: (BuildContext context) => FullScreenCodeDialog(exampleCodeTag: tag)
|
builder: (BuildContext context) => FullScreenCodeDialog(exampleCodeTag: tag)
|
||||||
@ -72,7 +72,7 @@ class _TabbedComponentDemoScaffoldState extends State<TabbedComponentDemoScaffol
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _showApiDocumentation(BuildContext context) async {
|
Future<void> _showApiDocumentation(BuildContext context) async {
|
||||||
final String? url = widget.demos![DefaultTabController.of(context)!.index].documentationUrl;
|
final String? url = widget.demos![DefaultTabController.of(context).index].documentationUrl;
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -451,7 +451,7 @@ class _AnimationDemoState extends State<AnimationDemo> with TickerProviderStateM
|
|||||||
return FloatingActionButton(
|
return FloatingActionButton(
|
||||||
child: const Icon(Icons.refresh),
|
child: const Icon(Icons.refresh),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_play(_allDemos[DefaultTabController.of(context)!.index]);
|
_play(_allDemos[DefaultTabController.of(context).index]);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -172,8 +172,8 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
|
|||||||
markers[MarkerType.topLeft] = box!.localToGlobal(Offset.zero);
|
markers[MarkerType.topLeft] = box!.localToGlobal(Offset.zero);
|
||||||
final Size size = box.size;
|
final Size size = box.size;
|
||||||
markers[MarkerType.bottomRight] = box.localToGlobal(Offset(size.width, size.height));
|
markers[MarkerType.bottomRight] = box.localToGlobal(Offset(size.width, size.height));
|
||||||
final ScrollableState? scrollable = Scrollable.of(target.currentContext!);
|
final ScrollableState scrollable = Scrollable.of(target.currentContext!);
|
||||||
markersScrollOffset = scrollable!.position.pixels;
|
markersScrollOffset = scrollable.position.pixels;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class FromSectionExample extends StatelessWidget {
|
|||||||
child: Form(
|
child: Form(
|
||||||
autovalidateMode: AutovalidateMode.always,
|
autovalidateMode: AutovalidateMode.always,
|
||||||
onChanged: () {
|
onChanged: () {
|
||||||
Form.of(primaryFocus!.context!)?.save();
|
Form.maybeOf(primaryFocus!.context!)?.save();
|
||||||
},
|
},
|
||||||
child: CupertinoFormSection.insetGrouped(
|
child: CupertinoFormSection.insetGrouped(
|
||||||
header: const Text('SECTION 1'),
|
header: const Text('SECTION 1'),
|
||||||
|
@ -38,7 +38,7 @@ class MyStatelessWidget extends StatelessWidget {
|
|||||||
// The Builder widget is used to have a different BuildContext to access
|
// The Builder widget is used to have a different BuildContext to access
|
||||||
// closest DefaultTabController.
|
// closest DefaultTabController.
|
||||||
child: Builder(builder: (BuildContext context) {
|
child: Builder(builder: (BuildContext context) {
|
||||||
final TabController tabController = DefaultTabController.of(context)!;
|
final TabController tabController = DefaultTabController.of(context);
|
||||||
tabController.addListener(() {
|
tabController.addListener(() {
|
||||||
if (!tabController.indexIsChanging) {
|
if (!tabController.indexIsChanging) {
|
||||||
// Your code goes here.
|
// Your code goes here.
|
||||||
|
@ -44,7 +44,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
|||||||
child: Form(
|
child: Form(
|
||||||
autovalidateMode: AutovalidateMode.always,
|
autovalidateMode: AutovalidateMode.always,
|
||||||
onChanged: () {
|
onChanged: () {
|
||||||
Form.of(primaryFocus!.context!)!.save();
|
Form.of(primaryFocus!.context!).save();
|
||||||
},
|
},
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: List<Widget>.generate(5, (int index) {
|
children: List<Widget>.generate(5, (int index) {
|
||||||
|
@ -90,7 +90,7 @@ class CupertinoPageScaffold extends StatefulWidget {
|
|||||||
class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
|
class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
|
||||||
|
|
||||||
void _handleStatusBarTap() {
|
void _handleStatusBarTap() {
|
||||||
final ScrollController? primaryScrollController = PrimaryScrollController.of(context);
|
final ScrollController? primaryScrollController = PrimaryScrollController.maybeOf(context);
|
||||||
// Only act on the scroll controller if it has any attached scroll positions.
|
// Only act on the scroll controller if it has any attached scroll positions.
|
||||||
if (primaryScrollController != null && primaryScrollController.hasClients) {
|
if (primaryScrollController != null && primaryScrollController.hasClients) {
|
||||||
primaryScrollController.animateTo(
|
primaryScrollController.animateTo(
|
||||||
|
@ -602,7 +602,7 @@ class _PackagesViewState extends State<_PackagesView> {
|
|||||||
}
|
}
|
||||||
final String packageName = data.packages[widget.selectedId.value ?? 0];
|
final String packageName = data.packages[widget.selectedId.value ?? 0];
|
||||||
final List<int> bindings = data.packageLicenseBindings[packageName]!;
|
final List<int> bindings = data.packageLicenseBindings[packageName]!;
|
||||||
_MasterDetailFlow.of(context)!.setInitialDetailPage(
|
_MasterDetailFlow.of(context).setInitialDetailPage(
|
||||||
_DetailArguments(
|
_DetailArguments(
|
||||||
packageName,
|
packageName,
|
||||||
bindings.map((int i) => data.licenses[i]).toList(growable: false),
|
bindings.map((int i) => data.licenses[i]).toList(growable: false),
|
||||||
@ -632,7 +632,7 @@ class _PackagesViewState extends State<_PackagesView> {
|
|||||||
numberLicenses: bindings.length,
|
numberLicenses: bindings.length,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.selectedId.value = packageIndex;
|
widget.selectedId.value = packageIndex;
|
||||||
_MasterDetailFlow.of(context)!.openDetailPage(_DetailArguments(
|
_MasterDetailFlow.of(context).openDetailPage(_DetailArguments(
|
||||||
packageName,
|
packageName,
|
||||||
bindings.map((int i) => data.licenses[i]).toList(growable: false),
|
bindings.map((int i) => data.licenses[i]).toList(growable: false),
|
||||||
));
|
));
|
||||||
@ -1073,7 +1073,7 @@ class _MasterDetailFlow extends StatefulWidget {
|
|||||||
// ```dart
|
// ```dart
|
||||||
// _MasterDetailFlow.of(context).openDetailPage(arguments);
|
// _MasterDetailFlow.of(context).openDetailPage(arguments);
|
||||||
// ```
|
// ```
|
||||||
static _MasterDetailFlowProxy? of(BuildContext context) {
|
static _MasterDetailFlowProxy of(BuildContext context) {
|
||||||
_PageOpener? pageOpener = context.findAncestorStateOfType<_MasterDetailScaffoldState>();
|
_PageOpener? pageOpener = context.findAncestorStateOfType<_MasterDetailScaffoldState>();
|
||||||
pageOpener ??= context.findAncestorStateOfType<_MasterDetailFlowState>();
|
pageOpener ??= context.findAncestorStateOfType<_MasterDetailFlowState>();
|
||||||
assert(() {
|
assert(() {
|
||||||
@ -1086,7 +1086,7 @@ class _MasterDetailFlow extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
return pageOpener != null ? _MasterDetailFlowProxy._(pageOpener) : null;
|
return _MasterDetailFlowProxy._(pageOpener!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,13 +1339,13 @@ class _MasterDetailScaffoldState extends State<_MasterDetailScaffold>
|
|||||||
@override
|
@override
|
||||||
void openDetailPage(Object arguments) {
|
void openDetailPage(Object arguments) {
|
||||||
SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
||||||
_MasterDetailFlow.of(context)!.openDetailPage(arguments);
|
_MasterDetailFlow.of(context).openDetailPage(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void setInitialDetailPage(Object arguments) {
|
void setInitialDetailPage(Object arguments) {
|
||||||
SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
SchedulerBinding.instance.addPostFrameCallback((_) => _detailArguments.value = arguments);
|
||||||
_MasterDetailFlow.of(context)!.setInitialDetailPage(arguments);
|
_MasterDetailFlow.of(context).setInitialDetailPage(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -820,13 +820,9 @@ class _AppBarState extends State<AppBar> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
if (_scrollNotificationObserver != null) {
|
_scrollNotificationObserver?.removeListener(_handleScrollNotification);
|
||||||
_scrollNotificationObserver!.removeListener(_handleScrollNotification);
|
_scrollNotificationObserver = ScrollNotificationObserver.maybeOf(context);
|
||||||
}
|
_scrollNotificationObserver?.addListener(_handleScrollNotification);
|
||||||
_scrollNotificationObserver = ScrollNotificationObserver.of(context);
|
|
||||||
if (_scrollNotificationObserver != null) {
|
|
||||||
_scrollNotificationObserver!.addListener(_handleScrollNotification);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -806,7 +806,7 @@ class _FocusedDate extends InheritedWidget {
|
|||||||
return !DateUtils.isSameDay(date, oldWidget.date);
|
return !DateUtils.isSameDay(date, oldWidget.date);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DateTime? of(BuildContext context) {
|
static DateTime? maybeOf(BuildContext context) {
|
||||||
final _FocusedDate? focusedDate = context.dependOnInheritedWidgetOfExactType<_FocusedDate>();
|
final _FocusedDate? focusedDate = context.dependOnInheritedWidgetOfExactType<_FocusedDate>();
|
||||||
return focusedDate?.date;
|
return focusedDate?.date;
|
||||||
}
|
}
|
||||||
@ -887,7 +887,7 @@ class _DayPickerState extends State<_DayPicker> {
|
|||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
// Check to see if the focused date is in this month, if so focus it.
|
// Check to see if the focused date is in this month, if so focus it.
|
||||||
final DateTime? focusedDate = _FocusedDate.of(context);
|
final DateTime? focusedDate = _FocusedDate.maybeOf(context);
|
||||||
if (focusedDate != null && DateUtils.isSameMonth(widget.displayedMonth, focusedDate)) {
|
if (focusedDate != null && DateUtils.isSameMonth(widget.displayedMonth, focusedDate)) {
|
||||||
_dayFocusNodes[focusedDate.day - 1].requestFocus();
|
_dayFocusNodes[focusedDate.day - 1].requestFocus();
|
||||||
}
|
}
|
||||||
|
@ -1940,12 +1940,11 @@ class _FocusedDate extends InheritedWidget {
|
|||||||
return !DateUtils.isSameDay(date, oldWidget.date) || scrollDirection != oldWidget.scrollDirection;
|
return !DateUtils.isSameDay(date, oldWidget.date) || scrollDirection != oldWidget.scrollDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _FocusedDate? of(BuildContext context) {
|
static _FocusedDate? maybeOf(BuildContext context) {
|
||||||
return context.dependOnInheritedWidgetOfExactType<_FocusedDate>();
|
return context.dependOnInheritedWidgetOfExactType<_FocusedDate>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _DayHeaders extends StatelessWidget {
|
class _DayHeaders extends StatelessWidget {
|
||||||
const _DayHeaders();
|
const _DayHeaders();
|
||||||
|
|
||||||
@ -2217,7 +2216,7 @@ class _MonthItemState extends State<_MonthItem> {
|
|||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
// Check to see if the focused date is in this month, if so focus it.
|
// Check to see if the focused date is in this month, if so focus it.
|
||||||
final DateTime? focusedDate = _FocusedDate.of(context)?.date;
|
final DateTime? focusedDate = _FocusedDate.maybeOf(context)?.date;
|
||||||
if (focusedDate != null && DateUtils.isSameMonth(widget.displayedMonth, focusedDate)) {
|
if (focusedDate != null && DateUtils.isSameMonth(widget.displayedMonth, focusedDate)) {
|
||||||
_dayFocusNodes[focusedDate.day - 1].requestFocus();
|
_dayFocusNodes[focusedDate.day - 1].requestFocus();
|
||||||
}
|
}
|
||||||
@ -2237,7 +2236,7 @@ class _MonthItemState extends State<_MonthItem> {
|
|||||||
|
|
||||||
void _dayFocusChanged(bool focused) {
|
void _dayFocusChanged(bool focused) {
|
||||||
if (focused) {
|
if (focused) {
|
||||||
final TraversalDirection? focusDirection = _FocusedDate.of(context)?.scrollDirection;
|
final TraversalDirection? focusDirection = _FocusedDate.maybeOf(context)?.scrollDirection;
|
||||||
if (focusDirection != null) {
|
if (focusDirection != null) {
|
||||||
ScrollPositionAlignmentPolicy policy = ScrollPositionAlignmentPolicy.explicit;
|
ScrollPositionAlignmentPolicy policy = ScrollPositionAlignmentPolicy.explicit;
|
||||||
switch (focusDirection) {
|
switch (focusDirection) {
|
||||||
|
@ -332,7 +332,7 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
|
|||||||
_iconColor = _controller.drive(_iconColorTween.chain(_easeInTween));
|
_iconColor = _controller.drive(_iconColorTween.chain(_easeInTween));
|
||||||
_backgroundColor = _controller.drive(_backgroundColorTween.chain(_easeOutTween));
|
_backgroundColor = _controller.drive(_backgroundColorTween.chain(_easeOutTween));
|
||||||
|
|
||||||
_isExpanded = PageStorage.of(context)?.readState(context) as bool? ?? widget.initiallyExpanded;
|
_isExpanded = PageStorage.maybeOf(context)?.readState(context) as bool? ?? widget.initiallyExpanded;
|
||||||
if (_isExpanded) {
|
if (_isExpanded) {
|
||||||
_controller.value = 1.0;
|
_controller.value = 1.0;
|
||||||
}
|
}
|
||||||
@ -359,7 +359,7 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PageStorage.of(context)?.writeState(context, _isExpanded);
|
PageStorage.maybeOf(context)?.writeState(context, _isExpanded);
|
||||||
});
|
});
|
||||||
widget.onExpansionChanged?.call(_isExpanded);
|
widget.onExpansionChanged?.call(_isExpanded);
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ class _InkState extends State<Ink> {
|
|||||||
_ink = InkDecoration(
|
_ink = InkDecoration(
|
||||||
decoration: widget.decoration,
|
decoration: widget.decoration,
|
||||||
configuration: createLocalImageConfiguration(context),
|
configuration: createLocalImageConfiguration(context),
|
||||||
controller: Material.of(context)!,
|
controller: Material.of(context),
|
||||||
referenceBox: _boxKey.currentContext!.findRenderObject()! as RenderBox,
|
referenceBox: _boxKey.currentContext!.findRenderObject()! as RenderBox,
|
||||||
onRemoved: _handleRemoved,
|
onRemoved: _handleRemoved,
|
||||||
);
|
);
|
||||||
|
@ -197,7 +197,7 @@ class _ParentInkResponseProvider extends InheritedWidget {
|
|||||||
@override
|
@override
|
||||||
bool updateShouldNotify(_ParentInkResponseProvider oldWidget) => state != oldWidget.state;
|
bool updateShouldNotify(_ParentInkResponseProvider oldWidget) => state != oldWidget.state;
|
||||||
|
|
||||||
static _ParentInkResponseState? of(BuildContext context) {
|
static _ParentInkResponseState? maybeOf(BuildContext context) {
|
||||||
return context.dependOnInheritedWidgetOfExactType<_ParentInkResponseProvider>()?.state;
|
return context.dependOnInheritedWidgetOfExactType<_ParentInkResponseProvider>()?.state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -600,7 +600,7 @@ class InkResponse extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final _ParentInkResponseState? parentState = _ParentInkResponseProvider.of(context);
|
final _ParentInkResponseState? parentState = _ParentInkResponseProvider.maybeOf(context);
|
||||||
return _InkResponseStateWidget(
|
return _InkResponseStateWidget(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
onTapDown: onTapDown,
|
onTapDown: onTapDown,
|
||||||
@ -916,7 +916,7 @@ class _InkResponseState extends State<_InkResponseStateWidget>
|
|||||||
}
|
}
|
||||||
final RenderBox referenceBox = context.findRenderObject()! as RenderBox;
|
final RenderBox referenceBox = context.findRenderObject()! as RenderBox;
|
||||||
_highlights[type] = InkHighlight(
|
_highlights[type] = InkHighlight(
|
||||||
controller: Material.of(context)!,
|
controller: Material.of(context),
|
||||||
referenceBox: referenceBox,
|
referenceBox: referenceBox,
|
||||||
color: resolvedOverlayColor,
|
color: resolvedOverlayColor,
|
||||||
shape: widget.highlightShape,
|
shape: widget.highlightShape,
|
||||||
@ -952,7 +952,7 @@ class _InkResponseState extends State<_InkResponseStateWidget>
|
|||||||
}
|
}
|
||||||
|
|
||||||
InteractiveInkFeature _createInkFeature(Offset globalPosition) {
|
InteractiveInkFeature _createInkFeature(Offset globalPosition) {
|
||||||
final MaterialInkController inkController = Material.of(context)!;
|
final MaterialInkController inkController = Material.of(context);
|
||||||
final RenderBox referenceBox = context.findRenderObject()! as RenderBox;
|
final RenderBox referenceBox = context.findRenderObject()! as RenderBox;
|
||||||
final Offset position = referenceBox.globalToLocal(globalPosition);
|
final Offset position = referenceBox.globalToLocal(globalPosition);
|
||||||
final Color color = widget.overlayColor?.resolve(statesController.value) ?? widget.splashColor ?? Theme.of(context).splashColor;
|
final Color color = widget.overlayColor?.resolve(statesController.value) ?? widget.splashColor ?? Theme.of(context).splashColor;
|
||||||
|
@ -348,14 +348,55 @@ class Material extends StatefulWidget {
|
|||||||
/// Typical usage is as follows:
|
/// Typical usage is as follows:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// MaterialInkController? inkController = Material.of(context);
|
/// MaterialInkController? inkController = Material.maybeOf(context);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// This method can be expensive (it walks the element tree).
|
/// This method can be expensive (it walks the element tree).
|
||||||
static MaterialInkController? of(BuildContext context) {
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Material.of], which is similar to this method, but asserts if
|
||||||
|
/// no [Material] ancestor is found.
|
||||||
|
static MaterialInkController? maybeOf(BuildContext context) {
|
||||||
return context.findAncestorRenderObjectOfType<_RenderInkFeatures>();
|
return context.findAncestorRenderObjectOfType<_RenderInkFeatures>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The ink controller from the closest instance of [Material] that encloses
|
||||||
|
/// the given context.
|
||||||
|
///
|
||||||
|
/// If no [Material] widget ancestor can be found then this method will assert
|
||||||
|
/// in debug mode, and throw an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Typical usage is as follows:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// MaterialInkController inkController = Material.of(context);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This method can be expensive (it walks the element tree).
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Material.maybeOf], which is similar to this method, but returns null if
|
||||||
|
/// no [Material] ancestor is found.
|
||||||
|
static MaterialInkController of(BuildContext context) {
|
||||||
|
final MaterialInkController? controller = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (controller == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'Material.of() was called with a context that does not contain a Material widget.\n'
|
||||||
|
'No Material widget ancestor could be found starting from the context that was passed to '
|
||||||
|
'Material.of(). This can happen because you are using a widget that looks for a Material '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return controller!;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<Material> createState() => _MaterialState();
|
State<Material> createState() => _MaterialState();
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ class _MenuAnchorState extends State<MenuAnchor> {
|
|||||||
_parent = _MenuAnchorState._maybeOf(context);
|
_parent = _MenuAnchorState._maybeOf(context);
|
||||||
_parent?._addChild(this);
|
_parent?._addChild(this);
|
||||||
_position?.isScrollingNotifier.removeListener(_handleScroll);
|
_position?.isScrollingNotifier.removeListener(_handleScroll);
|
||||||
_position = Scrollable.of(context)?.position;
|
_position = Scrollable.maybeOf(context)?.position;
|
||||||
_position?.isScrollingNotifier.addListener(_handleScroll);
|
_position?.isScrollingNotifier.addListener(_handleScroll);
|
||||||
final Size newSize = MediaQuery.of(context).size;
|
final Size newSize = MediaQuery.of(context).size;
|
||||||
if (_viewSize != null && newSize != _viewSize) {
|
if (_viewSize != null && newSize != _viewSize) {
|
||||||
|
@ -267,7 +267,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_firstRowIndex = PageStorage.of(context)?.readState(context) as int? ?? widget.initialFirstRowIndex ?? 0;
|
_firstRowIndex = PageStorage.maybeOf(context)?.readState(context) as int? ?? widget.initialFirstRowIndex ?? 0;
|
||||||
widget.source.addListener(_handleDataSourceChanged);
|
widget.source.addListener(_handleDataSourceChanged);
|
||||||
_handleDataSourceChanged();
|
_handleDataSourceChanged();
|
||||||
}
|
}
|
||||||
|
@ -2536,7 +2536,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
|
|||||||
// top. We implement this by looking up the primary scroll controller and
|
// top. We implement this by looking up the primary scroll controller and
|
||||||
// scrolling it to the top when tapped.
|
// scrolling it to the top when tapped.
|
||||||
void _handleStatusBarTap() {
|
void _handleStatusBarTap() {
|
||||||
final ScrollController? primaryScrollController = PrimaryScrollController.of(context);
|
final ScrollController? primaryScrollController = PrimaryScrollController.maybeOf(context);
|
||||||
if (primaryScrollController != null && primaryScrollController.hasClients) {
|
if (primaryScrollController != null && primaryScrollController.hasClients) {
|
||||||
primaryScrollController.animateTo(
|
primaryScrollController.animateTo(
|
||||||
0.0,
|
0.0,
|
||||||
|
@ -375,18 +375,65 @@ class DefaultTabController extends StatefulWidget {
|
|||||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
/// The closest instance of this class that encloses the given context.
|
/// The closest instance of [DefaultTabController] that encloses the given
|
||||||
|
/// context, or null if none is found.
|
||||||
///
|
///
|
||||||
/// {@tool snippet}
|
/// {@tool snippet} Typical usage is as follows:
|
||||||
/// Typical usage is as follows:
|
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// TabController controller = DefaultTabController.of(context)!;
|
/// TabController? controller = DefaultTabController.maybeOf(context);
|
||||||
/// ```
|
/// ```
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
static TabController? of(BuildContext context) {
|
///
|
||||||
final _TabControllerScope? scope = context.dependOnInheritedWidgetOfExactType<_TabControllerScope>();
|
/// Calling this method will create a dependency on the closest
|
||||||
return scope?.controller;
|
/// [DefaultTabController] in the [context], if there is one.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [DefaultTabController.of], which is similar to this method, but asserts
|
||||||
|
/// if no [DefaultTabController] ancestor is found.
|
||||||
|
static TabController? maybeOf(BuildContext context) {
|
||||||
|
return context.dependOnInheritedWidgetOfExactType<_TabControllerScope>()?.controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The closest instance of [DefaultTabController] that encloses the given
|
||||||
|
/// context.
|
||||||
|
///
|
||||||
|
/// If no instance is found, this method will assert in debug mode and throw
|
||||||
|
/// an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [DefaultTabController] in the [context].
|
||||||
|
///
|
||||||
|
/// {@tool snippet} Typical usage is as follows:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// TabController controller = DefaultTabController.of(context);
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [DefaultTabController.maybeOf], which is similar to this method, but
|
||||||
|
/// returns null if no [DefaultTabController] ancestor is found.
|
||||||
|
static TabController of(BuildContext context) {
|
||||||
|
final TabController? controller = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (controller == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'DefaultTabController.of() was called with a context that does not '
|
||||||
|
'contain a DefaultTabController widget.\n'
|
||||||
|
'No DefaultTabController widget ancestor could be found starting from '
|
||||||
|
'the context that was passed to DefaultTabController.of(). This can '
|
||||||
|
'happen because you are using a widget that looks for a DefaultTabController '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return controller!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -954,7 +954,7 @@ class _TabBarState extends State<TabBar> {
|
|||||||
// TODO(xu-baolin): Remove automatic adjustment to white color indicator
|
// TODO(xu-baolin): Remove automatic adjustment to white color indicator
|
||||||
// with a better long-term solution.
|
// with a better long-term solution.
|
||||||
// https://github.com/flutter/flutter/pull/68171#pullrequestreview-517753917
|
// https://github.com/flutter/flutter/pull/68171#pullrequestreview-517753917
|
||||||
if (widget.automaticIndicatorColorAdjustment && color.value == Material.of(context)?.color?.value) {
|
if (widget.automaticIndicatorColorAdjustment && color.value == Material.maybeOf(context)?.color?.value) {
|
||||||
color = Colors.white;
|
color = Colors.white;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,7 +972,7 @@ class _TabBarState extends State<TabBar> {
|
|||||||
bool get _controllerIsValid => _controller?.animation != null;
|
bool get _controllerIsValid => _controller?.animation != null;
|
||||||
|
|
||||||
void _updateTabController() {
|
void _updateTabController() {
|
||||||
final TabController? newController = widget.controller ?? DefaultTabController.of(context);
|
final TabController? newController = widget.controller ?? DefaultTabController.maybeOf(context);
|
||||||
assert(() {
|
assert(() {
|
||||||
if (newController == null) {
|
if (newController == null) {
|
||||||
throw FlutterError(
|
throw FlutterError(
|
||||||
@ -1411,7 +1411,7 @@ class _TabBarViewState extends State<TabBarView> {
|
|||||||
bool get _controllerIsValid => _controller?.animation != null;
|
bool get _controllerIsValid => _controller?.animation != null;
|
||||||
|
|
||||||
void _updateTabController() {
|
void _updateTabController() {
|
||||||
final TabController? newController = widget.controller ?? DefaultTabController.of(context);
|
final TabController? newController = widget.controller ?? DefaultTabController.maybeOf(context);
|
||||||
assert(() {
|
assert(() {
|
||||||
if (newController == null) {
|
if (newController == null) {
|
||||||
throw FlutterError(
|
throw FlutterError(
|
||||||
@ -1768,7 +1768,7 @@ class TabPageSelector extends StatelessWidget {
|
|||||||
final Color fixSelectedColor = selectedColor ?? Theme.of(context).colorScheme.secondary;
|
final Color fixSelectedColor = selectedColor ?? Theme.of(context).colorScheme.secondary;
|
||||||
final ColorTween selectedColorTween = ColorTween(begin: fixColor, end: fixSelectedColor);
|
final ColorTween selectedColorTween = ColorTween(begin: fixColor, end: fixSelectedColor);
|
||||||
final ColorTween previousColorTween = ColorTween(begin: fixSelectedColor, end: fixColor);
|
final ColorTween previousColorTween = ColorTween(begin: fixSelectedColor, end: fixColor);
|
||||||
final TabController? tabController = controller ?? DefaultTabController.of(context);
|
final TabController? tabController = controller ?? DefaultTabController.maybeOf(context);
|
||||||
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
||||||
assert(() {
|
assert(() {
|
||||||
if (tabController == null) {
|
if (tabController == null) {
|
||||||
|
@ -38,7 +38,12 @@ abstract class RenderAbstractViewport extends RenderObject {
|
|||||||
///
|
///
|
||||||
/// If the object does not have a [RenderAbstractViewport] as an ancestor,
|
/// If the object does not have a [RenderAbstractViewport] as an ancestor,
|
||||||
/// this function returns null.
|
/// this function returns null.
|
||||||
static RenderAbstractViewport? of(RenderObject? object) {
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [RenderAbstractViewport.of], which is similar to this method, but
|
||||||
|
/// asserts if no [RenderAbstractViewport] ancestor is found.
|
||||||
|
static RenderAbstractViewport? maybeOf(RenderObject? object) {
|
||||||
while (object != null) {
|
while (object != null) {
|
||||||
if (object is RenderAbstractViewport) {
|
if (object is RenderAbstractViewport) {
|
||||||
return object;
|
return object;
|
||||||
@ -48,6 +53,35 @@ abstract class RenderAbstractViewport extends RenderObject {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [RenderAbstractViewport] that most tightly encloses the given
|
||||||
|
/// render object.
|
||||||
|
///
|
||||||
|
/// If the object does not have a [RenderAbstractViewport] as an ancestor,
|
||||||
|
/// this function will assert in debug mode, and throw an exception in release
|
||||||
|
/// mode.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [RenderAbstractViewport.maybeOf], which is similar to this method, but
|
||||||
|
/// returns null if no [RenderAbstractViewport] ancestor is found.
|
||||||
|
static RenderAbstractViewport of(RenderObject? object) {
|
||||||
|
final RenderAbstractViewport? viewport = maybeOf(object);
|
||||||
|
assert(() {
|
||||||
|
if (viewport == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'RenderAbstractViewport.of() was called with a render object that was '
|
||||||
|
'not a descendant of a RenderAbstractViewport.\n'
|
||||||
|
'No RenderAbstractViewport render object ancestor could be found starting '
|
||||||
|
'from the object that was passed to RenderAbstractViewport.of().\n'
|
||||||
|
'The render object where the viewport search started was:\n'
|
||||||
|
' $object',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return viewport!;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the offset that would be needed to reveal the `target`
|
/// Returns the offset that would be needed to reveal the `target`
|
||||||
/// [RenderObject].
|
/// [RenderObject].
|
||||||
///
|
///
|
||||||
|
@ -72,19 +72,62 @@ class AutofillGroup extends StatefulWidget {
|
|||||||
this.onDisposeAction = AutofillContextAction.commit,
|
this.onDisposeAction = AutofillContextAction.commit,
|
||||||
}) : assert(child != null);
|
}) : assert(child != null);
|
||||||
|
|
||||||
/// Returns the closest [AutofillGroupState] which encloses the given context.
|
/// Returns the [AutofillGroupState] of the closest [AutofillGroup] widget
|
||||||
|
/// which encloses the given context, or null if one cannot be found.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [AutofillGroup] in the [context], if there is one.
|
||||||
///
|
///
|
||||||
/// {@macro flutter.widgets.AutofillGroupState}
|
/// {@macro flutter.widgets.AutofillGroupState}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
|
/// * [AutofillGroup.of], which is similar to this method, but asserts if an
|
||||||
|
/// [AutofillGroup] cannot be found.
|
||||||
/// * [EditableTextState], where this method is used to retrieve the closest
|
/// * [EditableTextState], where this method is used to retrieve the closest
|
||||||
/// [AutofillGroupState].
|
/// [AutofillGroupState].
|
||||||
static AutofillGroupState? of(BuildContext context) {
|
static AutofillGroupState? maybeOf(BuildContext context) {
|
||||||
final _AutofillScope? scope = context.dependOnInheritedWidgetOfExactType<_AutofillScope>();
|
final _AutofillScope? scope = context.dependOnInheritedWidgetOfExactType<_AutofillScope>();
|
||||||
return scope?._scope;
|
return scope?._scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [AutofillGroupState] of the closest [AutofillGroup] widget
|
||||||
|
/// which encloses the given context.
|
||||||
|
///
|
||||||
|
/// If no instance is found, this method will assert in debug mode and throw
|
||||||
|
/// an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [AutofillGroup] in the [context].
|
||||||
|
///
|
||||||
|
/// {@macro flutter.widgets.AutofillGroupState}
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [AutofillGroup.maybeOf], which is similar to this method, but returns
|
||||||
|
/// null if an [AutofillGroup] cannot be found.
|
||||||
|
/// * [EditableTextState], where this method is used to retrieve the closest
|
||||||
|
/// [AutofillGroupState].
|
||||||
|
static AutofillGroupState of(BuildContext context) {
|
||||||
|
final AutofillGroupState? groupState = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (groupState == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'AutofillGroup.of() was called with a context that does not contain an '
|
||||||
|
'AutofillGroup widget.\n'
|
||||||
|
'No AutofillGroup widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to AutofillGroup.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for an AutofillGroup '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return groupState!;
|
||||||
|
}
|
||||||
|
|
||||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
@ -171,7 +214,7 @@ class AutofillGroupState extends State<AutofillGroup> with AutofillScopeMixin {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_isTopmostAutofillGroup = AutofillGroup.of(context) == null;
|
_isTopmostAutofillGroup = AutofillGroup.maybeOf(context) == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -2373,7 +2373,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
|
||||||
final AutofillGroupState? newAutofillGroup = AutofillGroup.of(context);
|
final AutofillGroupState? newAutofillGroup = AutofillGroup.maybeOf(context);
|
||||||
if (currentAutofillScope != newAutofillGroup) {
|
if (currentAutofillScope != newAutofillGroup) {
|
||||||
_currentAutofillScope?.unregister(autofillId);
|
_currentAutofillScope?.unregister(autofillId);
|
||||||
_currentAutofillScope = newAutofillGroup;
|
_currentAutofillScope = newAutofillGroup;
|
||||||
@ -3481,7 +3481,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
textAlign: widget.textAlign,
|
textAlign: widget.textAlign,
|
||||||
textDirection: _textDirection,
|
textDirection: _textDirection,
|
||||||
textScaleFactor: widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
|
textScaleFactor: widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
|
||||||
textHeightBehavior: widget.textHeightBehavior ?? DefaultTextHeightBehavior.of(context),
|
textHeightBehavior: widget.textHeightBehavior ?? DefaultTextHeightBehavior.maybeOf(context),
|
||||||
locale: widget.locale,
|
locale: widget.locale,
|
||||||
structStyle: widget.strutStyle,
|
structStyle: widget.strutStyle,
|
||||||
placeholder: _placeholderLocation,
|
placeholder: _placeholderLocation,
|
||||||
@ -4150,7 +4150,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
textAlign: widget.textAlign,
|
textAlign: widget.textAlign,
|
||||||
textDirection: _textDirection,
|
textDirection: _textDirection,
|
||||||
locale: widget.locale,
|
locale: widget.locale,
|
||||||
textHeightBehavior: widget.textHeightBehavior ?? DefaultTextHeightBehavior.of(context),
|
textHeightBehavior: widget.textHeightBehavior ?? DefaultTextHeightBehavior.maybeOf(context),
|
||||||
textWidthBasis: widget.textWidthBasis,
|
textWidthBasis: widget.textWidthBasis,
|
||||||
obscuringCharacter: widget.obscuringCharacter,
|
obscuringCharacter: widget.obscuringCharacter,
|
||||||
obscureText: widget.obscureText,
|
obscureText: widget.obscureText,
|
||||||
|
@ -623,7 +623,7 @@ mixin DirectionalFocusTraversalPolicyMixin on FocusTraversalPolicy {
|
|||||||
// Returns true if successfully popped the history.
|
// Returns true if successfully popped the history.
|
||||||
bool popOrInvalidate(TraversalDirection direction) {
|
bool popOrInvalidate(TraversalDirection direction) {
|
||||||
final FocusNode lastNode = policyData.history.removeLast().node;
|
final FocusNode lastNode = policyData.history.removeLast().node;
|
||||||
if (Scrollable.of(lastNode.context!) != Scrollable.of(primaryFocus!.context!)) {
|
if (Scrollable.maybeOf(lastNode.context!) != Scrollable.maybeOf(primaryFocus!.context!)) {
|
||||||
invalidateScopeData(nearestScope);
|
invalidateScopeData(nearestScope);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -741,7 +741,7 @@ mixin DirectionalFocusTraversalPolicyMixin on FocusTraversalPolicy {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
FocusNode? found;
|
FocusNode? found;
|
||||||
final ScrollableState? focusedScrollable = Scrollable.of(focusedChild.context!);
|
final ScrollableState? focusedScrollable = Scrollable.maybeOf(focusedChild.context!);
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case TraversalDirection.down:
|
case TraversalDirection.down:
|
||||||
case TraversalDirection.up:
|
case TraversalDirection.up:
|
||||||
@ -751,7 +751,7 @@ mixin DirectionalFocusTraversalPolicyMixin on FocusTraversalPolicy {
|
|||||||
nearestScope.traversalDescendants,
|
nearestScope.traversalDescendants,
|
||||||
);
|
);
|
||||||
if (focusedScrollable != null && !focusedScrollable.position.atEdge) {
|
if (focusedScrollable != null && !focusedScrollable.position.atEdge) {
|
||||||
final Iterable<FocusNode> filteredEligibleNodes = eligibleNodes!.where((FocusNode node) => Scrollable.of(node.context!) == focusedScrollable);
|
final Iterable<FocusNode> filteredEligibleNodes = eligibleNodes!.where((FocusNode node) => Scrollable.maybeOf(node.context!) == focusedScrollable);
|
||||||
if (filteredEligibleNodes.isNotEmpty) {
|
if (filteredEligibleNodes.isNotEmpty) {
|
||||||
eligibleNodes = filteredEligibleNodes;
|
eligibleNodes = filteredEligibleNodes;
|
||||||
}
|
}
|
||||||
@ -783,7 +783,7 @@ mixin DirectionalFocusTraversalPolicyMixin on FocusTraversalPolicy {
|
|||||||
case TraversalDirection.left:
|
case TraversalDirection.left:
|
||||||
Iterable<FocusNode>? eligibleNodes = _sortAndFilterHorizontally(direction, focusedChild.rect, nearestScope);
|
Iterable<FocusNode>? eligibleNodes = _sortAndFilterHorizontally(direction, focusedChild.rect, nearestScope);
|
||||||
if (focusedScrollable != null && !focusedScrollable.position.atEdge) {
|
if (focusedScrollable != null && !focusedScrollable.position.atEdge) {
|
||||||
final Iterable<FocusNode> filteredEligibleNodes = eligibleNodes!.where((FocusNode node) => Scrollable.of(node.context!) == focusedScrollable);
|
final Iterable<FocusNode> filteredEligibleNodes = eligibleNodes!.where((FocusNode node) => Scrollable.maybeOf(node.context!) == focusedScrollable);
|
||||||
if (filteredEligibleNodes.isNotEmpty) {
|
if (filteredEligibleNodes.isNotEmpty) {
|
||||||
eligibleNodes = filteredEligibleNodes;
|
eligibleNodes = filteredEligibleNodes;
|
||||||
}
|
}
|
||||||
|
@ -49,20 +49,66 @@ class Form extends StatefulWidget {
|
|||||||
}) : assert(child != null),
|
}) : assert(child != null),
|
||||||
autovalidateMode = autovalidateMode ?? AutovalidateMode.disabled;
|
autovalidateMode = autovalidateMode ?? AutovalidateMode.disabled;
|
||||||
|
|
||||||
/// Returns the closest [FormState] which encloses the given context,
|
/// Returns the [FormState] of the closest [Form] widget which encloses the
|
||||||
/// or null if there is no such form.
|
/// given context, or null if none is found.
|
||||||
///
|
///
|
||||||
/// Typical usage is as follows:
|
/// Typical usage is as follows:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// FormState form = Form.of(context)!;
|
/// FormState? form = Form.maybeOf(context);
|
||||||
/// form.save();
|
/// form?.save();
|
||||||
/// ```
|
/// ```
|
||||||
static FormState? of(BuildContext context) {
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest [Form] in the
|
||||||
|
/// [context], if there is one.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Form.of], which is similar to this method, but asserts if no [Form]
|
||||||
|
/// ancestor is found.
|
||||||
|
static FormState? maybeOf(BuildContext context) {
|
||||||
final _FormScope? scope = context.dependOnInheritedWidgetOfExactType<_FormScope>();
|
final _FormScope? scope = context.dependOnInheritedWidgetOfExactType<_FormScope>();
|
||||||
return scope?._formState;
|
return scope?._formState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [FormState] of the closest [Form] widget which encloses the
|
||||||
|
/// given context.
|
||||||
|
///
|
||||||
|
/// Typical usage is as follows:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// FormState form = Form.of(context);
|
||||||
|
/// form.save();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If no [Form] ancestor is found, this will assert in debug mode, and throw
|
||||||
|
/// an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest [Form] in the
|
||||||
|
/// [context].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Form.maybeOf], which is similar to this method, but returns null if no
|
||||||
|
/// [Form] ancestor is found.
|
||||||
|
static FormState of(BuildContext context) {
|
||||||
|
final FormState? formState = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (formState == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'Form.of() was called with a context that does not contain a Form widget.\n'
|
||||||
|
'No Form widget ancestor could be found starting from the context that '
|
||||||
|
'was passed to Form.of(). This can happen because you are using a widget '
|
||||||
|
'that looks for a Form ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return formState!;
|
||||||
|
}
|
||||||
|
|
||||||
/// The widget below this widget in the tree.
|
/// The widget below this widget in the tree.
|
||||||
///
|
///
|
||||||
/// This is the root of the widget hierarchy that contains this form.
|
/// This is the root of the widget hierarchy that contains this form.
|
||||||
@ -380,7 +426,7 @@ class FormFieldState<T> extends State<FormField<T>> with RestorationMixin {
|
|||||||
_hasInteractedByUser.value = false;
|
_hasInteractedByUser.value = false;
|
||||||
_errorText.value = null;
|
_errorText.value = null;
|
||||||
});
|
});
|
||||||
Form.of(context)?._fieldDidChange();
|
Form.maybeOf(context)?._fieldDidChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls [FormField.validator] to set the [errorText]. Returns true if there
|
/// Calls [FormField.validator] to set the [errorText]. Returns true if there
|
||||||
@ -414,7 +460,7 @@ class FormFieldState<T> extends State<FormField<T>> with RestorationMixin {
|
|||||||
_value = value;
|
_value = value;
|
||||||
_hasInteractedByUser.value = true;
|
_hasInteractedByUser.value = true;
|
||||||
});
|
});
|
||||||
Form.of(context)?._fieldDidChange();
|
Form.maybeOf(context)?._fieldDidChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the value associated with this form field.
|
/// Sets the value associated with this form field.
|
||||||
@ -441,7 +487,7 @@ class FormFieldState<T> extends State<FormField<T>> with RestorationMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void deactivate() {
|
void deactivate() {
|
||||||
Form.of(context)?._unregister(this);
|
Form.maybeOf(context)?._unregister(this);
|
||||||
super.deactivate();
|
super.deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +507,7 @@ class FormFieldState<T> extends State<FormField<T>> with RestorationMixin {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Form.of(context)?._register(this);
|
Form.maybeOf(context)?._register(this);
|
||||||
return widget.builder(this);
|
return widget.builder(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1605,8 +1605,12 @@ abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
|
|||||||
///
|
///
|
||||||
/// final Color color;
|
/// final Color color;
|
||||||
///
|
///
|
||||||
|
/// static FrogColor? maybeOf(BuildContext context) {
|
||||||
|
/// return context.dependOnInheritedWidgetOfExactType<FrogColor>();
|
||||||
|
/// }
|
||||||
|
///
|
||||||
/// static FrogColor of(BuildContext context) {
|
/// static FrogColor of(BuildContext context) {
|
||||||
/// final FrogColor? result = context.dependOnInheritedWidgetOfExactType<FrogColor>();
|
/// final FrogColor? result = maybeOf(context);
|
||||||
/// assert(result != null, 'No FrogColor found in context');
|
/// assert(result != null, 'No FrogColor found in context');
|
||||||
/// return result!;
|
/// return result!;
|
||||||
/// }
|
/// }
|
||||||
@ -1617,30 +1621,35 @@ abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
|
|||||||
/// ```
|
/// ```
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
///
|
///
|
||||||
/// ## Implementing the `of` method
|
/// ## Implementing the `of` and `maybeOf` methods
|
||||||
///
|
///
|
||||||
/// The convention is to provide a static method `of` on the [InheritedWidget]
|
/// The convention is to provide two static methods, `of` and `maybeOf`, on the
|
||||||
/// which does the call to [BuildContext.dependOnInheritedWidgetOfExactType]. This
|
/// [InheritedWidget] which call
|
||||||
/// allows the class to define its own fallback logic in case there isn't
|
/// [BuildContext.dependOnInheritedWidgetOfExactType]. This allows the class to
|
||||||
/// a widget in scope. In the example above, the value returned will be
|
/// define its own fallback logic in case there isn't a widget in scope.
|
||||||
/// null in that case, but it could also have defaulted to a value.
|
|
||||||
///
|
///
|
||||||
/// Sometimes, the `of` method returns the data rather than the inherited
|
/// The `of` method typically returns a non-nullable instance and asserts if the
|
||||||
/// widget; for example, in this case it could have returned a [Color] instead
|
/// [InheritedWidget] isn't found, and the `maybeOf` method returns a nullable
|
||||||
/// of the `FrogColor` widget.
|
/// instance, and returns null if the [InheritedWidget] isn't found. The `of`
|
||||||
|
/// method is typically implemented by calling `maybeOf` internally.
|
||||||
|
///
|
||||||
|
/// Sometimes, the `of` and `maybeOf` methods return some data rather than the
|
||||||
|
/// inherited widget itself; for example, in this case it could have returned a
|
||||||
|
/// [Color] instead of the `FrogColor` widget.
|
||||||
///
|
///
|
||||||
/// Occasionally, the inherited widget is an implementation detail of another
|
/// Occasionally, the inherited widget is an implementation detail of another
|
||||||
/// class, and is therefore private. The `of` method in that case is typically
|
/// class, and is therefore private. The `of` and `maybeOf` methods in that case
|
||||||
/// put on the public class instead. For example, [Theme] is implemented as a
|
/// are typically implemented on the public class instead. For example, [Theme]
|
||||||
/// [StatelessWidget] that builds a private inherited widget; [Theme.of] looks
|
/// is implemented as a [StatelessWidget] that builds a private inherited
|
||||||
/// for that inherited widget using [BuildContext.dependOnInheritedWidgetOfExactType]
|
/// widget; [Theme.of] looks for that private inherited widget using
|
||||||
/// and then returns the [ThemeData].
|
/// [BuildContext.dependOnInheritedWidgetOfExactType] and then returns the
|
||||||
|
/// [ThemeData] inside it.
|
||||||
///
|
///
|
||||||
/// ## Calling the `of` method
|
/// ## Calling the `of` or `maybeOf` methods
|
||||||
///
|
///
|
||||||
/// When using the `of` method, the `context` must be a descendant of the
|
/// When using the `of` or `maybeOf` methods, the `context` must be a descendant
|
||||||
/// [InheritedWidget], meaning it must be "below" the [InheritedWidget] in the
|
/// of the [InheritedWidget], meaning it must be "below" the [InheritedWidget]
|
||||||
/// tree.
|
/// in the tree.
|
||||||
///
|
///
|
||||||
/// {@tool snippet}
|
/// {@tool snippet}
|
||||||
///
|
///
|
||||||
@ -1674,8 +1683,9 @@ abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
|
|||||||
///
|
///
|
||||||
/// {@tool snippet}
|
/// {@tool snippet}
|
||||||
///
|
///
|
||||||
/// In this example, the `context` used is the one from the `MyOtherPage` widget,
|
/// In this example, the `context` used is the one from the `MyOtherPage`
|
||||||
/// which is a parent of the `FrogColor` widget, so this does not work.
|
/// widget, which is a parent of the `FrogColor` widget, so this does not work,
|
||||||
|
/// and will assert when `FrogColor.of` is called.
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// // continuing from previous example...
|
/// // continuing from previous example...
|
||||||
@ -1697,21 +1707,20 @@ abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget {
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// {@end-tool}
|
/// {@end-tool} {@youtube 560 315 https://www.youtube.com/watch?v=1t-8rBCGBYw}
|
||||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=1t-8rBCGBYw}
|
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [StatefulWidget] and [State], for widgets that can build differently
|
/// * [StatefulWidget] and [State], for widgets that can build differently
|
||||||
/// several times over their lifetime.
|
/// several times over their lifetime.
|
||||||
/// * [StatelessWidget], for widgets that always build the same way given a
|
/// * [StatelessWidget], for widgets that always build the same way given a
|
||||||
/// particular configuration and ambient state.
|
/// particular configuration and ambient state.
|
||||||
/// * [Widget], for an overview of widgets in general.
|
/// * [Widget], for an overview of widgets in general.
|
||||||
/// * [InheritedNotifier], an inherited widget whose value can be a
|
/// * [InheritedNotifier], an inherited widget whose value can be a
|
||||||
/// [Listenable], and which will notify dependents whenever the value
|
/// [Listenable], and which will notify dependents whenever the value sends
|
||||||
/// sends notifications.
|
/// notifications.
|
||||||
/// * [InheritedModel], an inherited widget that allows clients to subscribe
|
/// * [InheritedModel], an inherited widget that allows clients to subscribe to
|
||||||
/// to changes for subparts of the value.
|
/// changes for subparts of the value.
|
||||||
abstract class InheritedWidget extends ProxyWidget {
|
abstract class InheritedWidget extends ProxyWidget {
|
||||||
/// Abstract const constructor. This constructor enables subclasses to provide
|
/// Abstract const constructor. This constructor enables subclasses to provide
|
||||||
/// const constructors so that they can be used in const expressions.
|
/// const constructors so that they can be used in const expressions.
|
||||||
|
@ -6,53 +6,61 @@ import 'dart:collection';
|
|||||||
|
|
||||||
import 'framework.dart';
|
import 'framework.dart';
|
||||||
|
|
||||||
/// An [InheritedWidget] that's intended to be used as the base class for
|
/// An [InheritedWidget] that's intended to be used as the base class for models
|
||||||
/// models whose dependents may only depend on one part or "aspect" of the
|
/// whose dependents may only depend on one part or "aspect" of the overall
|
||||||
/// overall model.
|
/// model.
|
||||||
///
|
///
|
||||||
/// An inherited widget's dependents are unconditionally rebuilt when the
|
/// An inherited widget's dependents are unconditionally rebuilt when the
|
||||||
/// inherited widget changes per [InheritedWidget.updateShouldNotify].
|
/// inherited widget changes per [InheritedWidget.updateShouldNotify]. This
|
||||||
/// This widget is similar except that dependents aren't rebuilt
|
/// widget is similar except that dependents aren't rebuilt unconditionally.
|
||||||
/// unconditionally.
|
|
||||||
///
|
///
|
||||||
/// Widgets that depend on an [InheritedModel] qualify their dependence
|
/// Widgets that depend on an [InheritedModel] qualify their dependence with a
|
||||||
/// with a value that indicates what "aspect" of the model they depend
|
/// value that indicates what "aspect" of the model they depend on. When the
|
||||||
/// on. When the model is rebuilt, dependents will also be rebuilt, but
|
/// model is rebuilt, dependents will also be rebuilt, but only if there was a
|
||||||
/// only if there was a change in the model that corresponds to the aspect
|
/// change in the model that corresponds to the aspect they provided.
|
||||||
/// they provided.
|
|
||||||
///
|
///
|
||||||
/// The type parameter `T` is the type of the model aspect objects.
|
/// The type parameter `T` is the type of the model aspect objects.
|
||||||
///
|
///
|
||||||
/// {@youtube 560 315 https://www.youtube.com/watch?v=ml5uefGgkaA}
|
/// {@youtube 560 315 https://www.youtube.com/watch?v=ml5uefGgkaA}
|
||||||
///
|
///
|
||||||
/// Widgets create a dependency on an [InheritedModel] with a static method:
|
/// Widgets create a dependency on an [InheritedModel] with a static method:
|
||||||
/// [InheritedModel.inheritFrom]. This method's `context` parameter
|
/// [InheritedModel.inheritFrom]. This method's `context` parameter defines the
|
||||||
/// defines the subtree that will be rebuilt when the model changes.
|
/// subtree that will be rebuilt when the model changes. Typically the
|
||||||
/// Typically the `inheritFrom` method is called from a model-specific
|
/// `inheritFrom` method is called from a model-specific static `maybeOf` or
|
||||||
/// static `of` method. For example:
|
/// `of` methods, a convention that is present in many Flutter framework classes
|
||||||
|
/// which look things up. For example:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// class MyModel extends InheritedModel<String> {
|
/// class MyModel extends InheritedModel<String> {
|
||||||
/// const MyModel({super.key, required super.child});
|
/// const MyModel({super.key, required super.child});
|
||||||
|
///
|
||||||
/// // ...
|
/// // ...
|
||||||
/// static MyModel? of(BuildContext context, String aspect) {
|
/// static MyModel? maybeOf(BuildContext context, [String? aspect]) {
|
||||||
/// return InheritedModel.inheritFrom<MyModel>(context, aspect: aspect);
|
/// return InheritedModel.inheritFrom<MyModel>(context, aspect: aspect);
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
/// // ...
|
||||||
|
/// static MyModel of(BuildContext context, [String? aspect]) {
|
||||||
|
/// final MyModel? result = maybeOf(context, aspect);
|
||||||
|
/// assert(result != null, 'Unable to find an instance of MyModel...');
|
||||||
|
/// return result!;
|
||||||
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Calling `MyModel.of(context, 'foo')` means that `context` should only
|
/// Calling `MyModel.of(context, 'foo')` or `MyModel.maybeOf(context,
|
||||||
/// be rebuilt when the `foo` aspect of `MyModel` changes. If the aspect
|
/// 'foo')` means that `context` should only be rebuilt when the `foo` aspect of
|
||||||
/// is null, then the model supports all aspects.
|
/// `MyModel` changes. If the `aspect` is null, then the model supports all
|
||||||
|
/// aspects.
|
||||||
///
|
///
|
||||||
/// {@tool snippet}
|
/// {@tool snippet}
|
||||||
/// When the inherited model is rebuilt the [updateShouldNotify] and
|
/// When the inherited model is rebuilt the [updateShouldNotify] and
|
||||||
/// [updateShouldNotifyDependent] methods are used to decide what
|
/// [updateShouldNotifyDependent] methods are used to decide what should be
|
||||||
/// should be rebuilt. If [updateShouldNotify] returns true, then the
|
/// rebuilt. If [updateShouldNotify] returns true, then the inherited model's
|
||||||
/// inherited model's [updateShouldNotifyDependent] method is tested for
|
/// [updateShouldNotifyDependent] method is tested for each dependent and the
|
||||||
/// each dependent and the set of aspect objects it depends on.
|
/// set of aspect objects it depends on. The [updateShouldNotifyDependent]
|
||||||
/// The [updateShouldNotifyDependent] method must compare the set of aspect
|
/// method must compare the set of aspect dependencies with the changes in the
|
||||||
/// dependencies with the changes in the model itself. For example:
|
/// model itself. For example:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// class ABModel extends InheritedModel<String> {
|
/// class ABModel extends InheritedModel<String> {
|
||||||
@ -85,26 +93,26 @@ import 'framework.dart';
|
|||||||
/// In the previous example the dependencies checked by
|
/// In the previous example the dependencies checked by
|
||||||
/// [updateShouldNotifyDependent] are just the aspect strings passed to
|
/// [updateShouldNotifyDependent] are just the aspect strings passed to
|
||||||
/// `dependOnInheritedWidgetOfExactType`. They're represented as a [Set] because
|
/// `dependOnInheritedWidgetOfExactType`. They're represented as a [Set] because
|
||||||
/// one Widget can depend on more than one aspect of the model.
|
/// one Widget can depend on more than one aspect of the model. If a widget
|
||||||
/// If a widget depends on the model but doesn't specify an aspect,
|
/// depends on the model but doesn't specify an aspect, then changes in the
|
||||||
/// then changes in the model will cause the widget to be rebuilt
|
/// model will cause the widget to be rebuilt unconditionally.
|
||||||
/// unconditionally.
|
|
||||||
///
|
///
|
||||||
/// {@tool dartpad}
|
/// {@tool dartpad}
|
||||||
/// This example shows how to implement [InheritedModel] to rebuild a
|
/// This example shows how to implement [InheritedModel] to rebuild a widget
|
||||||
/// widget based on a qualified dependence. When tapped on the "Resize Logo" button
|
/// based on a qualified dependence. When tapped on the "Resize Logo" button
|
||||||
/// only the logo widget is rebuilt while the background widget remains unaffected.
|
/// only the logo widget is rebuilt while the background widget remains
|
||||||
|
/// unaffected.
|
||||||
///
|
///
|
||||||
/// ** See code in examples/api/lib/widgets/inherited_model/inherited_model.0.dart **
|
/// ** See code in examples/api/lib/widgets/inherited_model/inherited_model.0.dart **
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [InheritedWidget], an inherited widget that only notifies dependents
|
/// * [InheritedWidget], an inherited widget that only notifies dependents when
|
||||||
/// when its value is different.
|
/// its value is different.
|
||||||
/// * [InheritedNotifier], an inherited widget whose value can be a
|
/// * [InheritedNotifier], an inherited widget whose value can be a
|
||||||
/// [Listenable], and which will notify dependents whenever the value
|
/// [Listenable], and which will notify dependents whenever the value sends
|
||||||
/// sends notifications.
|
/// notifications.
|
||||||
abstract class InheritedModel<T> extends InheritedWidget {
|
abstract class InheritedModel<T> extends InheritedWidget {
|
||||||
/// Creates an inherited widget that supports dependencies qualified by
|
/// Creates an inherited widget that supports dependencies qualified by
|
||||||
/// "aspects", i.e. a descendant widget can indicate that it should
|
/// "aspects", i.e. a descendant widget can indicate that it should
|
||||||
|
@ -689,12 +689,53 @@ class HeroControllerScope extends InheritedWidget {
|
|||||||
final HeroController? controller;
|
final HeroController? controller;
|
||||||
|
|
||||||
/// Retrieves the [HeroController] from the closest [HeroControllerScope]
|
/// Retrieves the [HeroController] from the closest [HeroControllerScope]
|
||||||
/// ancestor.
|
/// ancestor, or null if none exists.
|
||||||
static HeroController? of(BuildContext context) {
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [HeroControllerScope] in the [context], if there is one.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [HeroControllerScope.of], which is similar to this method, but asserts
|
||||||
|
/// if no [HeroControllerScope] ancestor is found.
|
||||||
|
static HeroController? maybeOf(BuildContext context) {
|
||||||
final HeroControllerScope? host = context.dependOnInheritedWidgetOfExactType<HeroControllerScope>();
|
final HeroControllerScope? host = context.dependOnInheritedWidgetOfExactType<HeroControllerScope>();
|
||||||
return host?.controller;
|
return host?.controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the [HeroController] from the closest [HeroControllerScope]
|
||||||
|
/// ancestor.
|
||||||
|
///
|
||||||
|
/// If no ancestor is found, this method will assert in debug mode, and throw
|
||||||
|
/// an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [HeroControllerScope] in the [context].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [HeroControllerScope.maybeOf], which is similar to this method, but
|
||||||
|
/// returns null if no [HeroControllerScope] ancestor is found.
|
||||||
|
static HeroController of(BuildContext context) {
|
||||||
|
final HeroController? controller = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (controller == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'HeroControllerScope.of() was called with a context that does not contain a '
|
||||||
|
'HeroControllerScope widget.\n'
|
||||||
|
'No HeroControllerScope widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to HeroControllerScope.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for a HeroControllerScope '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return controller!;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool updateShouldNotify(HeroControllerScope oldWidget) {
|
bool updateShouldNotify(HeroControllerScope oldWidget) {
|
||||||
return oldWidget.controller != controller;
|
return oldWidget.controller != controller;
|
||||||
@ -3350,7 +3391,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_updateHeroController(HeroControllerScope.of(context));
|
_updateHeroController(HeroControllerScope.maybeOf(context));
|
||||||
for (final _RouteEntry entry in _history) {
|
for (final _RouteEntry entry in _history) {
|
||||||
entry.route.changedExternalState();
|
entry.route.changedExternalState();
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1088,7 @@ class _NestedScrollCoordinator implements ScrollActivityDelegate, ScrollHoldCont
|
|||||||
|
|
||||||
void updateParent() {
|
void updateParent() {
|
||||||
_outerPosition?.setParent(
|
_outerPosition?.setParent(
|
||||||
_parent ?? PrimaryScrollController.of(_state.context),
|
_parent ?? PrimaryScrollController.maybeOf(_state.context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,22 +174,66 @@ class PageStorage extends StatelessWidget {
|
|||||||
/// The page storage bucket to use for this subtree.
|
/// The page storage bucket to use for this subtree.
|
||||||
final PageStorageBucket bucket;
|
final PageStorageBucket bucket;
|
||||||
|
|
||||||
/// The bucket from the closest instance of this class that encloses the given context.
|
/// The [PageStorageBucket] from the closest instance of a [PageStorage]
|
||||||
|
/// widget that encloses the given context.
|
||||||
///
|
///
|
||||||
/// Returns null if none exists.
|
/// Returns null if none exists.
|
||||||
///
|
///
|
||||||
/// Typical usage is as follows:
|
/// Typical usage is as follows:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// PageStorageBucket bucket = PageStorage.of(context)!;
|
/// PageStorageBucket? bucket = PageStorage.of(context);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// This method can be expensive (it walks the element tree).
|
/// This method can be expensive (it walks the element tree).
|
||||||
static PageStorageBucket? of(BuildContext context) {
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [PageStorage.of], which is similar to this method, but
|
||||||
|
/// asserts if no [PageStorage] ancestor is found.
|
||||||
|
static PageStorageBucket? maybeOf(BuildContext context) {
|
||||||
final PageStorage? widget = context.findAncestorWidgetOfExactType<PageStorage>();
|
final PageStorage? widget = context.findAncestorWidgetOfExactType<PageStorage>();
|
||||||
return widget?.bucket;
|
return widget?.bucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [PageStorageBucket] from the closest instance of a [PageStorage]
|
||||||
|
/// widget that encloses the given context.
|
||||||
|
///
|
||||||
|
/// If no ancestor is found, this method will assert in debug mode, and throw
|
||||||
|
/// an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Typical usage is as follows:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// PageStorageBucket bucket = PageStorage.of(context);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This method can be expensive (it walks the element tree).
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [PageStorage.maybeOf], which is similar to this method, but
|
||||||
|
/// returns null if no [PageStorage] ancestor is found.
|
||||||
|
static PageStorageBucket of(BuildContext context) {
|
||||||
|
final PageStorageBucket? bucket = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (bucket == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'PageStorage.of() was called with a context that does not contain a '
|
||||||
|
'PageStorage widget.\n'
|
||||||
|
'No PageStorage widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to PageStorage.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for a PageStorage '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return bucket!;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => child;
|
Widget build(BuildContext context) => child;
|
||||||
}
|
}
|
||||||
|
@ -403,13 +403,13 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void saveScrollOffset() {
|
void saveScrollOffset() {
|
||||||
PageStorage.of(context.storageContext)?.writeState(context.storageContext, _cachedPage ?? getPageFromPixels(pixels, viewportDimension));
|
PageStorage.maybeOf(context.storageContext)?.writeState(context.storageContext, _cachedPage ?? getPageFromPixels(pixels, viewportDimension));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void restoreScrollOffset() {
|
void restoreScrollOffset() {
|
||||||
if (!hasPixels) {
|
if (!hasPixels) {
|
||||||
final double? value = PageStorage.of(context.storageContext)?.readState(context.storageContext) as double?;
|
final double? value = PageStorage.maybeOf(context.storageContext)?.readState(context.storageContext) as double?;
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
_pageToUseOnStartup = value;
|
_pageToUseOnStartup = value;
|
||||||
}
|
}
|
||||||
|
@ -125,11 +125,52 @@ class PrimaryScrollController extends InheritedWidget {
|
|||||||
///
|
///
|
||||||
/// Returns null if there is no [ScrollController] associated with the given
|
/// Returns null if there is no [ScrollController] associated with the given
|
||||||
/// context.
|
/// context.
|
||||||
static ScrollController? of(BuildContext context) {
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [PrimaryScrollController] in the [context], if there is one.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [PrimaryScrollController.maybeOf], which is similar to this method, but
|
||||||
|
/// asserts if no [PrimaryScrollController] ancestor is found.
|
||||||
|
static ScrollController? maybeOf(BuildContext context) {
|
||||||
final PrimaryScrollController? result = context.dependOnInheritedWidgetOfExactType<PrimaryScrollController>();
|
final PrimaryScrollController? result = context.dependOnInheritedWidgetOfExactType<PrimaryScrollController>();
|
||||||
return result?.controller;
|
return result?.controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [ScrollController] most closely associated with the given
|
||||||
|
/// context.
|
||||||
|
///
|
||||||
|
/// If no ancestor is found, this method will assert in debug mode, and throw
|
||||||
|
/// an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [PrimaryScrollController] in the [context].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [PrimaryScrollController.maybeOf], which is similar to this method, but
|
||||||
|
/// returns null if no [PrimaryScrollController] ancestor is found.
|
||||||
|
static ScrollController of(BuildContext context) {
|
||||||
|
final ScrollController? controller = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (controller == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'PrimaryScrollController.of() was called with a context that does not contain a '
|
||||||
|
'PrimaryScrollController widget.\n'
|
||||||
|
'No PrimaryScrollController widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to PrimaryScrollController.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for a PrimaryScrollController '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return controller!;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool updateShouldNotify(PrimaryScrollController oldWidget) => controller != oldWidget.controller;
|
bool updateShouldNotify(PrimaryScrollController oldWidget) => controller != oldWidget.controller;
|
||||||
|
|
||||||
|
@ -609,7 +609,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_scrollable = Scrollable.of(context)!;
|
_scrollable = Scrollable.of(context);
|
||||||
if (_autoScroller?.scrollable != _scrollable) {
|
if (_autoScroller?.scrollable != _scrollable) {
|
||||||
_autoScroller?.stopAutoScroll();
|
_autoScroller?.stopAutoScroll();
|
||||||
_autoScroller = EdgeDraggingAutoScroller(
|
_autoScroller = EdgeDraggingAutoScroller(
|
||||||
|
@ -65,18 +65,63 @@ class RestorationScope extends StatefulWidget {
|
|||||||
/// Returns the [RestorationBucket] inserted into the widget tree by the
|
/// Returns the [RestorationBucket] inserted into the widget tree by the
|
||||||
/// closest ancestor [RestorationScope] of `context`.
|
/// closest ancestor [RestorationScope] of `context`.
|
||||||
///
|
///
|
||||||
|
/// {@template flutter.widgets.restoration.RestorationScope.bucket_warning}
|
||||||
/// To avoid accidentally overwriting data already stored in the bucket by its
|
/// To avoid accidentally overwriting data already stored in the bucket by its
|
||||||
/// owner, data should not be stored directly in the bucket returned by this
|
/// owner, data should not be stored directly in the bucket returned by this
|
||||||
/// method. Instead, consider claiming a child bucket from the returned bucket
|
/// method. Instead, consider claiming a child bucket from the returned bucket
|
||||||
/// (via [RestorationBucket.claimChild]) and store the restoration data in
|
/// (via [RestorationBucket.claimChild]) and store the restoration data in
|
||||||
/// that child.
|
/// that child.
|
||||||
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// This method returns null if state restoration is turned off for this
|
/// This method returns null if state restoration is turned off for this
|
||||||
/// subtree.
|
/// subtree.
|
||||||
static RestorationBucket? of(BuildContext context) {
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [RestorationScope] in the [context], if there is one.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [RestorationScope.maybeOf], which is similar to this method, but asserts
|
||||||
|
/// if no [RestorationScope] ancestor is found.
|
||||||
|
static RestorationBucket? maybeOf(BuildContext context) {
|
||||||
return context.dependOnInheritedWidgetOfExactType<UnmanagedRestorationScope>()?.bucket;
|
return context.dependOnInheritedWidgetOfExactType<UnmanagedRestorationScope>()?.bucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [RestorationBucket] inserted into the widget tree by the
|
||||||
|
/// closest ancestor [RestorationScope] of `context`.
|
||||||
|
///
|
||||||
|
/// {@macro flutter.widgets.restoration.RestorationScope.bucket_warning}
|
||||||
|
///
|
||||||
|
/// This method will assert in debug mode and throw an exception in release
|
||||||
|
/// mode if state restoration is turned off for this subtree.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [RestorationScope] in the [context].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [RestorationScope.maybeOf], which is similar to this method, but returns
|
||||||
|
/// null if no [RestorationScope] ancestor is found.
|
||||||
|
static RestorationBucket of(BuildContext context) {
|
||||||
|
final RestorationBucket? bucket = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (bucket == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'RestorationScope.of() was called with a context that does not contain a '
|
||||||
|
'RestorationScope widget.\n'
|
||||||
|
'No RestorationScope widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to RestorationScope.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for a RestorationScope '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return bucket!;
|
||||||
|
}
|
||||||
|
|
||||||
/// The widget below this widget in the tree.
|
/// The widget below this widget in the tree.
|
||||||
///
|
///
|
||||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||||
@ -250,7 +295,7 @@ class _RootRestorationScopeState extends State<RootRestorationScope> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_ancestorBucket = RestorationScope.of(context);
|
_ancestorBucket = RestorationScope.maybeOf(context);
|
||||||
_loadRootBucketIfNecessary();
|
_loadRootBucketIfNecessary();
|
||||||
_okToRenderBlankContainer ??= widget.restorationId != null && _needsRootBucketInserted;
|
_okToRenderBlankContainer ??= widget.restorationId != null && _needsRootBucketInserted;
|
||||||
}
|
}
|
||||||
@ -834,7 +879,7 @@ mixin RestorationMixin<S extends StatefulWidget> on State<S> {
|
|||||||
if (restorationId == null) {
|
if (restorationId == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final RestorationBucket? potentialNewParent = RestorationScope.of(context);
|
final RestorationBucket? potentialNewParent = RestorationScope.maybeOf(context);
|
||||||
return potentialNewParent != _currentParent && (potentialNewParent?.isReplacing ?? false);
|
return potentialNewParent != _currentParent && (potentialNewParent?.isReplacing ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -850,7 +895,7 @@ mixin RestorationMixin<S extends StatefulWidget> on State<S> {
|
|||||||
|
|
||||||
final RestorationBucket? oldBucket = _bucket;
|
final RestorationBucket? oldBucket = _bucket;
|
||||||
final bool needsRestore = restorePending;
|
final bool needsRestore = restorePending;
|
||||||
_currentParent = RestorationScope.of(context);
|
_currentParent = RestorationScope.maybeOf(context);
|
||||||
|
|
||||||
final bool didReplaceBucket = _updateBucketIfNecessary(parent: _currentParent, restorePending: needsRestore);
|
final bool didReplaceBucket = _updateBucketIfNecessary(parent: _currentParent, restorePending: needsRestore);
|
||||||
|
|
||||||
|
@ -45,13 +45,13 @@ class _ListenerEntry extends LinkedListEntry<_ListenerEntry> {
|
|||||||
/// To add a listener to a [ScrollNotificationObserver] ancestor:
|
/// To add a listener to a [ScrollNotificationObserver] ancestor:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// ScrollNotificationObserver.of(context)!.addListener(_listener);
|
/// ScrollNotificationObserver.of(context).addListener(_listener);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// To remove the listener from a [ScrollNotificationObserver] ancestor:
|
/// To remove the listener from a [ScrollNotificationObserver] ancestor:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// ScrollNotificationObserver.of(context)!.removeListener(_listener);
|
/// ScrollNotificationObserver.of(context).removeListener(_listener);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Stateful widgets that share an ancestor [ScrollNotificationObserver] typically
|
/// Stateful widgets that share an ancestor [ScrollNotificationObserver] typically
|
||||||
@ -85,11 +85,52 @@ class ScrollNotificationObserver extends StatefulWidget {
|
|||||||
|
|
||||||
/// The closest instance of this class that encloses the given context.
|
/// The closest instance of this class that encloses the given context.
|
||||||
///
|
///
|
||||||
/// If there is no enclosing [ScrollNotificationObserver] widget, then null is returned.
|
/// If there is no enclosing [ScrollNotificationObserver] widget, then null is
|
||||||
static ScrollNotificationObserverState? of(BuildContext context) {
|
/// returned.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [ScrollNotificationObserver] in the [context], if there is one.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [ScrollNotificationObserver.of], which is similar to this method, but
|
||||||
|
/// asserts if no [ScrollNotificationObserver] ancestor is found.
|
||||||
|
static ScrollNotificationObserverState? maybeOf(BuildContext context) {
|
||||||
return context.dependOnInheritedWidgetOfExactType<_ScrollNotificationObserverScope>()?._scrollNotificationObserverState;
|
return context.dependOnInheritedWidgetOfExactType<_ScrollNotificationObserverScope>()?._scrollNotificationObserverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The closest instance of this class that encloses the given context.
|
||||||
|
///
|
||||||
|
/// If no ancestor is found, this method will assert in debug mode, and throw
|
||||||
|
/// an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [ScrollNotificationObserver] in the [context].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [ScrollNotificationObserver.maybeOf], which is similar to this method,
|
||||||
|
/// but returns null if no [ScrollNotificationObserver] ancestor is found.
|
||||||
|
static ScrollNotificationObserverState of(BuildContext context) {
|
||||||
|
final ScrollNotificationObserverState? observerState = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (observerState == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'ScrollNotificationObserver.of() was called with a context that does not contain a '
|
||||||
|
'ScrollNotificationObserver widget.\n'
|
||||||
|
'No ScrollNotificationObserver widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to ScrollNotificationObserver.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for a ScrollNotificationObserver '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return observerState!;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ScrollNotificationObserverState createState() => ScrollNotificationObserverState();
|
ScrollNotificationObserverState createState() => ScrollNotificationObserverState();
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
|
|||||||
// TODO(goderbauer): Deprecate this when state restoration supports all features of PageStorage.
|
// TODO(goderbauer): Deprecate this when state restoration supports all features of PageStorage.
|
||||||
@protected
|
@protected
|
||||||
void saveScrollOffset() {
|
void saveScrollOffset() {
|
||||||
PageStorage.of(context.storageContext)?.writeState(context.storageContext, pixels);
|
PageStorage.maybeOf(context.storageContext)?.writeState(context.storageContext, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called whenever the [ScrollPosition] is created, to restore the scroll
|
/// Called whenever the [ScrollPosition] is created, to restore the scroll
|
||||||
@ -424,7 +424,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
|
|||||||
@protected
|
@protected
|
||||||
void restoreScrollOffset() {
|
void restoreScrollOffset() {
|
||||||
if (!hasPixels) {
|
if (!hasPixels) {
|
||||||
final double? value = PageStorage.of(context.storageContext)?.readState(context.storageContext) as double?;
|
final double? value = PageStorage.maybeOf(context.storageContext)?.readState(context.storageContext) as double?;
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
correctPixels(value);
|
correctPixels(value);
|
||||||
}
|
}
|
||||||
@ -703,7 +703,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
|
|||||||
}) {
|
}) {
|
||||||
assert(alignmentPolicy != null);
|
assert(alignmentPolicy != null);
|
||||||
assert(object.attached);
|
assert(object.attached);
|
||||||
final RenderAbstractViewport viewport = RenderAbstractViewport.of(object)!;
|
final RenderAbstractViewport viewport = RenderAbstractViewport.of(object);
|
||||||
assert(viewport != null);
|
assert(viewport != null);
|
||||||
|
|
||||||
Rect? targetRect;
|
Rect? targetRect;
|
||||||
|
@ -411,7 +411,7 @@ abstract class ScrollView extends StatelessWidget {
|
|||||||
?? controller == null && PrimaryScrollController.shouldInherit(context, scrollDirection);
|
?? controller == null && PrimaryScrollController.shouldInherit(context, scrollDirection);
|
||||||
|
|
||||||
final ScrollController? scrollController = effectivePrimary
|
final ScrollController? scrollController = effectivePrimary
|
||||||
? PrimaryScrollController.of(context)
|
? PrimaryScrollController.maybeOf(context)
|
||||||
: controller;
|
: controller;
|
||||||
|
|
||||||
final Scrollable scrollable = Scrollable(
|
final Scrollable scrollable = Scrollable(
|
||||||
|
@ -289,21 +289,66 @@ class Scrollable extends StatefulWidget {
|
|||||||
properties.add(StringProperty('restorationId', restorationId));
|
properties.add(StringProperty('restorationId', restorationId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The state from the closest instance of this class that encloses the given context.
|
/// The state from the closest instance of this class that encloses the given
|
||||||
|
/// context, or null if none is found.
|
||||||
///
|
///
|
||||||
/// Typical usage is as follows:
|
/// Typical usage is as follows:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// ScrollableState scrollable = Scrollable.of(context)!;
|
/// ScrollableState? scrollable = Scrollable.maybeOf(context);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Calling this method will create a dependency on the closest [Scrollable]
|
/// Calling this method will create a dependency on the closest [Scrollable]
|
||||||
/// in the [context], if there is one.
|
/// in the [context], if there is one.
|
||||||
static ScrollableState? of(BuildContext context) {
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Scrollable.of], which is similar to this method, but asserts
|
||||||
|
/// if no [Scrollable] ancestor is found.
|
||||||
|
static ScrollableState? maybeOf(BuildContext context) {
|
||||||
final _ScrollableScope? widget = context.dependOnInheritedWidgetOfExactType<_ScrollableScope>();
|
final _ScrollableScope? widget = context.dependOnInheritedWidgetOfExactType<_ScrollableScope>();
|
||||||
return widget?.scrollable;
|
return widget?.scrollable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The state from the closest instance of this class that encloses the given
|
||||||
|
/// context.
|
||||||
|
///
|
||||||
|
/// Typical usage is as follows:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// ScrollableState scrollable = Scrollable.of(context);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest [Scrollable]
|
||||||
|
/// in the [context].
|
||||||
|
///
|
||||||
|
/// If no [Scrollable] ancestor is found, then this method will assert in
|
||||||
|
/// debug mode, and throw an exception in release mode.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Scrollable.maybeOf], which is similar to this method, but returns null
|
||||||
|
/// if no [Scrollable] ancestor is found.
|
||||||
|
static ScrollableState of(BuildContext context) {
|
||||||
|
final ScrollableState? scrollableState = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (scrollableState == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'Scrollable.of() was called with a context that does not contain a '
|
||||||
|
'Scrollable widget.\n'
|
||||||
|
'No Scrollable widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to Scrollable.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for a Scrollable '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return scrollableState!;
|
||||||
|
}
|
||||||
|
|
||||||
/// Provides a heuristic to determine if expensive frame-bound tasks should be
|
/// Provides a heuristic to determine if expensive frame-bound tasks should be
|
||||||
/// deferred for the [context] at a specific point in time.
|
/// deferred for the [context] at a specific point in time.
|
||||||
///
|
///
|
||||||
@ -343,7 +388,7 @@ class Scrollable extends StatefulWidget {
|
|||||||
// the `targetRenderObject` invisible.
|
// the `targetRenderObject` invisible.
|
||||||
// Also see https://github.com/flutter/flutter/issues/65100
|
// Also see https://github.com/flutter/flutter/issues/65100
|
||||||
RenderObject? targetRenderObject;
|
RenderObject? targetRenderObject;
|
||||||
ScrollableState? scrollable = Scrollable.of(context);
|
ScrollableState? scrollable = Scrollable.maybeOf(context);
|
||||||
while (scrollable != null) {
|
while (scrollable != null) {
|
||||||
futures.add(scrollable.position.ensureVisible(
|
futures.add(scrollable.position.ensureVisible(
|
||||||
context.findRenderObject()!,
|
context.findRenderObject()!,
|
||||||
@ -356,7 +401,7 @@ class Scrollable extends StatefulWidget {
|
|||||||
|
|
||||||
targetRenderObject = targetRenderObject ?? context.findRenderObject();
|
targetRenderObject = targetRenderObject ?? context.findRenderObject();
|
||||||
context = scrollable.context;
|
context = scrollable.context;
|
||||||
scrollable = Scrollable.of(context);
|
scrollable = Scrollable.maybeOf(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (futures.isEmpty || duration == Duration.zero) {
|
if (futures.isEmpty || duration == Duration.zero) {
|
||||||
@ -1618,11 +1663,11 @@ class ScrollAction extends Action<ScrollIntent> {
|
|||||||
final bool contextIsValid = focus != null && focus.context != null;
|
final bool contextIsValid = focus != null && focus.context != null;
|
||||||
if (contextIsValid) {
|
if (contextIsValid) {
|
||||||
// Check for primary scrollable within the current context
|
// Check for primary scrollable within the current context
|
||||||
if (Scrollable.of(focus.context!) != null) {
|
if (Scrollable.maybeOf(focus.context!) != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Check for fallback scrollable with context from PrimaryScrollController
|
// Check for fallback scrollable with context from PrimaryScrollController
|
||||||
final ScrollController? primaryScrollController = PrimaryScrollController.of(focus.context!);
|
final ScrollController? primaryScrollController = PrimaryScrollController.maybeOf(focus.context!);
|
||||||
return primaryScrollController != null && primaryScrollController.hasClients;
|
return primaryScrollController != null && primaryScrollController.hasClients;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1709,11 +1754,11 @@ class ScrollAction extends Action<ScrollIntent> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void invoke(ScrollIntent intent) {
|
void invoke(ScrollIntent intent) {
|
||||||
ScrollableState? state = Scrollable.of(primaryFocus!.context!);
|
ScrollableState? state = Scrollable.maybeOf(primaryFocus!.context!);
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
final ScrollController? primaryScrollController = PrimaryScrollController.of(primaryFocus!.context!);
|
final ScrollController primaryScrollController = PrimaryScrollController.of(primaryFocus!.context!);
|
||||||
assert (() {
|
assert (() {
|
||||||
if (primaryScrollController!.positions.length != 1) {
|
if (primaryScrollController.positions.length != 1) {
|
||||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||||
ErrorSummary(
|
ErrorSummary(
|
||||||
'A ScrollAction was invoked with the PrimaryScrollController, but '
|
'A ScrollAction was invoked with the PrimaryScrollController, but '
|
||||||
@ -1735,11 +1780,11 @@ class ScrollAction extends Action<ScrollIntent> {
|
|||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
if (primaryScrollController!.position.context.notificationContext == null
|
if (primaryScrollController.position.context.notificationContext == null
|
||||||
&& Scrollable.of(primaryScrollController.position.context.notificationContext!) == null) {
|
&& Scrollable.maybeOf(primaryScrollController.position.context.notificationContext!) == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state = Scrollable.of(primaryScrollController.position.context.notificationContext!);
|
state = Scrollable.maybeOf(primaryScrollController.position.context.notificationContext!);
|
||||||
}
|
}
|
||||||
assert(state != null, '$ScrollAction was invoked on a context that has no scrollable parent');
|
assert(state != null, '$ScrollAction was invoked on a context that has no scrollable parent');
|
||||||
assert(state!.position.hasPixels, 'Scrollable must be laid out before it can be scrolled via a ScrollAction');
|
assert(state!.position.hasPixels, 'Scrollable must be laid out before it can be scrolled via a ScrollAction');
|
||||||
|
@ -1550,7 +1550,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _validateInteractions(AnimationStatus status) {
|
void _validateInteractions(AnimationStatus status) {
|
||||||
final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.of(context);
|
final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.maybeOf(context);
|
||||||
if (status == AnimationStatus.dismissed) {
|
if (status == AnimationStatus.dismissed) {
|
||||||
assert(_fadeoutOpacityAnimation.value == 0.0);
|
assert(_fadeoutOpacityAnimation.value == 0.0);
|
||||||
// We do not check for a valid scroll position if the scrollbar is not
|
// We do not check for a valid scroll position if the scrollbar is not
|
||||||
@ -1566,7 +1566,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.of(context);
|
final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.maybeOf(context);
|
||||||
final bool tryPrimary = widget.controller == null;
|
final bool tryPrimary = widget.controller == null;
|
||||||
final String controllerForError = tryPrimary
|
final String controllerForError = tryPrimary
|
||||||
? 'PrimaryScrollController'
|
? 'PrimaryScrollController'
|
||||||
@ -1788,7 +1788,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
void handleThumbPressStart(Offset localPosition) {
|
void handleThumbPressStart(Offset localPosition) {
|
||||||
assert(_debugCheckHasValidScrollPosition());
|
assert(_debugCheckHasValidScrollPosition());
|
||||||
_currentController = widget.controller ?? PrimaryScrollController.of(context);
|
_currentController = widget.controller ?? PrimaryScrollController.maybeOf(context);
|
||||||
final Axis? direction = getScrollbarDirection();
|
final Axis? direction = getScrollbarDirection();
|
||||||
if (direction == null) {
|
if (direction == null) {
|
||||||
return;
|
return;
|
||||||
@ -1835,7 +1835,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
void _handleTrackTapDown(TapDownDetails details) {
|
void _handleTrackTapDown(TapDownDetails details) {
|
||||||
// The Scrollbar should page towards the position of the tap on the track.
|
// The Scrollbar should page towards the position of the tap on the track.
|
||||||
assert(_debugCheckHasValidScrollPosition());
|
assert(_debugCheckHasValidScrollPosition());
|
||||||
_currentController = widget.controller ?? PrimaryScrollController.of(context);
|
_currentController = widget.controller ?? PrimaryScrollController.maybeOf(context);
|
||||||
|
|
||||||
final ScrollPosition position = _currentController!.position;
|
final ScrollPosition position = _currentController!.position;
|
||||||
if (!position.physics.shouldAcceptUserOffset(position)) {
|
if (!position.physics.shouldAcceptUserOffset(position)) {
|
||||||
@ -1844,7 +1844,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
|
|
||||||
double scrollIncrement;
|
double scrollIncrement;
|
||||||
// Is an increment calculator available?
|
// Is an increment calculator available?
|
||||||
final ScrollIncrementCalculator? calculator = Scrollable.of(
|
final ScrollIncrementCalculator? calculator = Scrollable.maybeOf(
|
||||||
_currentController!.position.context.notificationContext!,
|
_currentController!.position.context.notificationContext!,
|
||||||
)?.widget.incrementCalculator;
|
)?.widget.incrementCalculator;
|
||||||
if (calculator != null) {
|
if (calculator != null) {
|
||||||
@ -1893,7 +1893,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
// ScrollController takes precedence over ScrollNotification
|
// ScrollController takes precedence over ScrollNotification
|
||||||
bool _shouldUpdatePainter(Axis notificationAxis) {
|
bool _shouldUpdatePainter(Axis notificationAxis) {
|
||||||
final ScrollController? scrollController = widget.controller ??
|
final ScrollController? scrollController = widget.controller ??
|
||||||
PrimaryScrollController.of(context);
|
PrimaryScrollController.maybeOf(context);
|
||||||
// Only update the painter of this scrollbar if the notification
|
// Only update the painter of this scrollbar if the notification
|
||||||
// metrics do not conflict with the information we have from the scroll
|
// metrics do not conflict with the information we have from the scroll
|
||||||
// controller.
|
// controller.
|
||||||
@ -1979,7 +1979,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
|
|||||||
|
|
||||||
Map<Type, GestureRecognizerFactory> get _gestures {
|
Map<Type, GestureRecognizerFactory> get _gestures {
|
||||||
final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};
|
final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};
|
||||||
final ScrollController? controller = widget.controller ?? PrimaryScrollController.of(context);
|
final ScrollController? controller = widget.controller ?? PrimaryScrollController.maybeOf(context);
|
||||||
if (controller == null || !enableGestures) {
|
if (controller == null || !enableGestures) {
|
||||||
return gestures;
|
return gestures;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ class SingleChildScrollView extends StatelessWidget {
|
|||||||
?? controller == null && PrimaryScrollController.shouldInherit(context, scrollDirection);
|
?? controller == null && PrimaryScrollController.shouldInherit(context, scrollDirection);
|
||||||
|
|
||||||
final ScrollController? scrollController = effectivePrimary
|
final ScrollController? scrollController = effectivePrimary
|
||||||
? PrimaryScrollController.of(context)
|
? PrimaryScrollController.maybeOf(context)
|
||||||
: controller;
|
: controller;
|
||||||
|
|
||||||
Widget scrollable = Scrollable(
|
Widget scrollable = Scrollable(
|
||||||
|
@ -212,7 +212,7 @@ class _FloatingHeaderState extends State<_FloatingHeader> {
|
|||||||
if (_position != null) {
|
if (_position != null) {
|
||||||
_position!.isScrollingNotifier.removeListener(_isScrollingListener);
|
_position!.isScrollingNotifier.removeListener(_isScrollingListener);
|
||||||
}
|
}
|
||||||
_position = Scrollable.of(context)?.position;
|
_position = Scrollable.maybeOf(context)?.position;
|
||||||
if (_position != null) {
|
if (_position != null) {
|
||||||
_position!.isScrollingNotifier.addListener(_isScrollingListener);
|
_position!.isScrollingNotifier.addListener(_isScrollingListener);
|
||||||
}
|
}
|
||||||
|
@ -245,19 +245,67 @@ class DefaultTextHeightBehavior extends InheritedTheme {
|
|||||||
/// {@macro dart.ui.textHeightBehavior}
|
/// {@macro dart.ui.textHeightBehavior}
|
||||||
final TextHeightBehavior textHeightBehavior;
|
final TextHeightBehavior textHeightBehavior;
|
||||||
|
|
||||||
/// The closest instance of this class that encloses the given context.
|
/// The closest instance of [DefaultTextHeightBehavior] that encloses the
|
||||||
|
/// given context, or null if none is found.
|
||||||
///
|
///
|
||||||
/// If no such instance exists, this method will return `null`.
|
/// If no such instance exists, this method will return `null`.
|
||||||
///
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [DefaultTextHeightBehavior] in the [context], if there is one.
|
||||||
|
///
|
||||||
/// Typical usage is as follows:
|
/// Typical usage is as follows:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// TextHeightBehavior defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context)!;
|
/// TextHeightBehavior? defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context);
|
||||||
/// ```
|
/// ```
|
||||||
static TextHeightBehavior? of(BuildContext context) {
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [DefaultTextHeightBehavior.maybeOf], which is similar to this method,
|
||||||
|
/// but asserts if no [DefaultTextHeightBehavior] ancestor is found.
|
||||||
|
static TextHeightBehavior? maybeOf(BuildContext context) {
|
||||||
return context.dependOnInheritedWidgetOfExactType<DefaultTextHeightBehavior>()?.textHeightBehavior;
|
return context.dependOnInheritedWidgetOfExactType<DefaultTextHeightBehavior>()?.textHeightBehavior;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The closest instance of [DefaultTextHeightBehavior] that encloses the
|
||||||
|
/// given context.
|
||||||
|
///
|
||||||
|
/// If no such instance exists, this method will assert in debug mode, and
|
||||||
|
/// throw an exception in release mode.
|
||||||
|
///
|
||||||
|
/// Typical usage is as follows:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// TextHeightBehavior defaultTextHeightBehavior = DefaultTextHeightBehavior.of(context);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Calling this method will create a dependency on the closest
|
||||||
|
/// [DefaultTextHeightBehavior] in the [context].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [DefaultTextHeightBehavior.maybeOf], which is similar to this method,
|
||||||
|
/// but returns null if no [DefaultTextHeightBehavior] ancestor is found.
|
||||||
|
static TextHeightBehavior of(BuildContext context) {
|
||||||
|
final TextHeightBehavior? behavior = maybeOf(context);
|
||||||
|
assert(() {
|
||||||
|
if (behavior == null) {
|
||||||
|
throw FlutterError(
|
||||||
|
'DefaultTextHeightBehavior.of() was called with a context that does not contain a '
|
||||||
|
'DefaultTextHeightBehavior widget.\n'
|
||||||
|
'No DefaultTextHeightBehavior widget ancestor could be found starting from the '
|
||||||
|
'context that was passed to DefaultTextHeightBehavior.of(). This can happen '
|
||||||
|
'because you are using a widget that looks for a DefaultTextHeightBehavior '
|
||||||
|
'ancestor, but no such ancestor exists.\n'
|
||||||
|
'The context used was:\n'
|
||||||
|
' $context',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
|
return behavior!;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool updateShouldNotify(DefaultTextHeightBehavior oldWidget) {
|
bool updateShouldNotify(DefaultTextHeightBehavior oldWidget) {
|
||||||
return textHeightBehavior != oldWidget.textHeightBehavior;
|
return textHeightBehavior != oldWidget.textHeightBehavior;
|
||||||
@ -564,7 +612,7 @@ class Text extends StatelessWidget {
|
|||||||
maxLines: maxLines ?? defaultTextStyle.maxLines,
|
maxLines: maxLines ?? defaultTextStyle.maxLines,
|
||||||
strutStyle: strutStyle,
|
strutStyle: strutStyle,
|
||||||
textWidthBasis: textWidthBasis ?? defaultTextStyle.textWidthBasis,
|
textWidthBasis: textWidthBasis ?? defaultTextStyle.textWidthBasis,
|
||||||
textHeightBehavior: textHeightBehavior ?? defaultTextStyle.textHeightBehavior ?? DefaultTextHeightBehavior.of(context),
|
textHeightBehavior: textHeightBehavior ?? defaultTextStyle.textHeightBehavior ?? DefaultTextHeightBehavior.maybeOf(context),
|
||||||
selectionRegistrar: registrar,
|
selectionRegistrar: registrar,
|
||||||
selectionColor: selectionColor ?? DefaultSelectionStyle.of(context).selectionColor ?? DefaultSelectionStyle.defaultColor,
|
selectionColor: selectionColor ?? DefaultSelectionStyle.of(context).selectionColor ?? DefaultSelectionStyle.defaultColor,
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
|
@ -1893,7 +1893,7 @@ class TextSelectionGestureDetectorBuilder {
|
|||||||
final ScrollableState? scrollableState =
|
final ScrollableState? scrollableState =
|
||||||
delegate.editableTextKey.currentContext == null
|
delegate.editableTextKey.currentContext == null
|
||||||
? null
|
? null
|
||||||
: Scrollable.of(delegate.editableTextKey.currentContext!);
|
: Scrollable.maybeOf(delegate.editableTextKey.currentContext!);
|
||||||
return scrollableState == null
|
return scrollableState == null
|
||||||
? 0.0
|
? 0.0
|
||||||
: scrollableState.position.pixels;
|
: scrollableState.position.pixels;
|
||||||
|
@ -51,7 +51,7 @@ Widget buildSliverAppBarApp({
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScrollController primaryScrollController(WidgetTester tester) {
|
ScrollController primaryScrollController(WidgetTester tester) {
|
||||||
return PrimaryScrollController.of(tester.element(find.byType(CustomScrollView)))!;
|
return PrimaryScrollController.of(tester.element(find.byType(CustomScrollView)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TextStyle? iconStyle(WidgetTester tester, IconData icon) {
|
TextStyle? iconStyle(WidgetTester tester, IconData icon) {
|
||||||
|
@ -1589,7 +1589,7 @@ void main() {
|
|||||||
|
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Content1')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Content1')));
|
||||||
await tester.pump(const Duration(milliseconds: 200)); // splash is well underway
|
await tester.pump(const Duration(milliseconds: 200)); // splash is well underway
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))as RenderBox;
|
||||||
expect(box, paints..circle(x: 68.0, y: 24.0, color: pressedColor));
|
expect(box, paints..circle(x: 68.0, y: 24.0, color: pressedColor));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
});
|
});
|
||||||
|
@ -1011,7 +1011,7 @@ void main() {
|
|||||||
await tester.tap(find.byKey(buttonKey));
|
await tester.tap(find.byKey(buttonKey));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)))!;
|
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)));
|
||||||
// Make sure there is no overscroll
|
// Make sure there is no overscroll
|
||||||
expect(scrollController.offset, scrollController.position.maxScrollExtent);
|
expect(scrollController.offset, scrollController.position.maxScrollExtent);
|
||||||
|
|
||||||
@ -1854,7 +1854,7 @@ void main() {
|
|||||||
|
|
||||||
double getMenuScroll() {
|
double getMenuScroll() {
|
||||||
double scrollPosition;
|
double scrollPosition;
|
||||||
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)))!;
|
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)));
|
||||||
assert(scrollController != null);
|
assert(scrollController != null);
|
||||||
scrollPosition = scrollController.position.pixels;
|
scrollPosition = scrollController.position.pixels;
|
||||||
assert(scrollPosition != null);
|
assert(scrollPosition != null);
|
||||||
@ -1890,7 +1890,7 @@ void main() {
|
|||||||
|
|
||||||
double getMenuScroll() {
|
double getMenuScroll() {
|
||||||
double scrollPosition;
|
double scrollPosition;
|
||||||
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)))!;
|
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)));
|
||||||
assert(scrollController != null);
|
assert(scrollController != null);
|
||||||
scrollPosition = scrollController.position.pixels;
|
scrollPosition = scrollController.position.pixels;
|
||||||
assert(scrollPosition != null);
|
assert(scrollPosition != null);
|
||||||
@ -1927,7 +1927,7 @@ void main() {
|
|||||||
|
|
||||||
double getMenuScroll() {
|
double getMenuScroll() {
|
||||||
double scrollPosition;
|
double scrollPosition;
|
||||||
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)))!;
|
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)));
|
||||||
assert(scrollController != null);
|
assert(scrollController != null);
|
||||||
scrollPosition = scrollController.position.pixels;
|
scrollPosition = scrollController.position.pixels;
|
||||||
assert(scrollPosition != null);
|
assert(scrollPosition != null);
|
||||||
@ -1964,7 +1964,7 @@ void main() {
|
|||||||
|
|
||||||
double getMenuScroll() {
|
double getMenuScroll() {
|
||||||
double scrollPosition;
|
double scrollPosition;
|
||||||
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)))!;
|
final ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)));
|
||||||
assert(scrollController != null);
|
assert(scrollController != null);
|
||||||
scrollPosition = scrollController.position.pixels;
|
scrollPosition = scrollController.position.pixels;
|
||||||
assert(scrollPosition != null);
|
assert(scrollPosition != null);
|
||||||
@ -3066,7 +3066,7 @@ void main() {
|
|||||||
await tester.tap(find.text('0'));
|
await tester.tap(find.text('0'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)))!;
|
ScrollController scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)));
|
||||||
// The scrollbar shouldn't show if the list fits into the screen.
|
// The scrollbar shouldn't show if the list fits into the screen.
|
||||||
expect(scrollController.position.maxScrollExtent, 0);
|
expect(scrollController.position.maxScrollExtent, 0);
|
||||||
expect(find.byType(Scrollbar), isNot(paints..rect()));
|
expect(find.byType(Scrollbar), isNot(paints..rect()));
|
||||||
@ -3082,7 +3082,7 @@ void main() {
|
|||||||
await tester.tap(find.text('0'));
|
await tester.tap(find.text('0'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)))!;
|
scrollController = PrimaryScrollController.of(tester.element(find.byType(ListView)));
|
||||||
// The scrollbar is shown when the list is longer than the height of the screen.
|
// The scrollbar is shown when the list is longer than the height of the screen.
|
||||||
expect(scrollController.position.maxScrollExtent > 0, isTrue);
|
expect(scrollController.position.maxScrollExtent > 0, isTrue);
|
||||||
expect(find.byType(Scrollbar), paints..rect());
|
expect(find.byType(Scrollbar), paints..rect());
|
||||||
|
@ -1279,7 +1279,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
@ -1290,7 +1290,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
|
@ -1307,7 +1307,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
@ -1318,7 +1318,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
|
@ -75,7 +75,7 @@ void main() {
|
|||||||
await tester.pump(); // start gesture
|
await tester.pump(); // start gesture
|
||||||
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
||||||
|
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
expect(
|
expect(
|
||||||
box,
|
box,
|
||||||
paints
|
paints
|
||||||
@ -127,7 +127,7 @@ void main() {
|
|||||||
await tester.tapAt(tapDownOffset);
|
await tester.tapAt(tapDownOffset);
|
||||||
await tester.pump(); // start gesture
|
await tester.pump(); // start gesture
|
||||||
|
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))as RenderBox;
|
||||||
|
|
||||||
bool offsetsAreClose(Offset a, Offset b) => (a - b).distance < 1.0;
|
bool offsetsAreClose(Offset a, Offset b) => (a - b).distance < 1.0;
|
||||||
bool radiiAreClose(double a, double b) => (a - b).abs() < 1.0;
|
bool radiiAreClose(double a, double b) => (a - b).abs() < 1.0;
|
||||||
@ -205,7 +205,7 @@ void main() {
|
|||||||
await tester.pump(); // start gesture
|
await tester.pump(); // start gesture
|
||||||
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
||||||
|
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))as RenderBox;
|
||||||
expect(
|
expect(
|
||||||
box,
|
box,
|
||||||
paints
|
paints
|
||||||
@ -337,7 +337,7 @@ void main() {
|
|||||||
await tester.sendKeyEvent(LogicalKeyboardKey.space);
|
await tester.sendKeyEvent(LogicalKeyboardKey.space);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))as RenderBox;
|
||||||
|
|
||||||
// ripplePattern always add a translation of topLeft.
|
// ripplePattern always add a translation of topLeft.
|
||||||
expect(box, ripplePattern(30.0, 0));
|
expect(box, ripplePattern(30.0, 0));
|
||||||
@ -433,7 +433,7 @@ void main() {
|
|||||||
await gesture.moveTo(Offset.zero);
|
await gesture.moveTo(Offset.zero);
|
||||||
await gesture.up(); // generates a tap cancel
|
await gesture.up(); // generates a tap cancel
|
||||||
|
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))as RenderBox;
|
||||||
expect(box, paints..everything((Symbol method, List<dynamic> arguments) {
|
expect(box, paints..everything((Symbol method, List<dynamic> arguments) {
|
||||||
if (method != #drawCircle) {
|
if (method != #drawCircle) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -50,7 +50,7 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(buttonFinder))!;
|
final MaterialInkController material = Material.of(tester.element(buttonFinder));
|
||||||
expect(material, paintsExactlyCountTimes(#drawRect, 1));
|
expect(material, paintsExactlyCountTimes(#drawRect, 1));
|
||||||
|
|
||||||
// ignore: avoid_dynamic_calls
|
// ignore: avoid_dynamic_calls
|
||||||
@ -81,7 +81,7 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(buttonFinder))!;
|
final MaterialInkController material = Material.of(tester.element(buttonFinder));
|
||||||
expect(material, paintsExactlyCountTimes(#drawPaint, 1));
|
expect(material, paintsExactlyCountTimes(#drawPaint, 1));
|
||||||
},
|
},
|
||||||
skip: kIsWeb, // [intended] shaders are not yet supported for web.
|
skip: kIsWeb, // [intended] shaders are not yet supported for web.
|
||||||
|
@ -48,7 +48,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
@ -59,7 +59,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame());
|
await tester.pumpWidget(buildFrame());
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
|
@ -865,7 +865,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)));
|
||||||
|
|
||||||
// Press
|
// Press
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(innerKey)), pointer: 1);
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(innerKey)), pointer: 1);
|
||||||
@ -938,7 +938,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)));
|
||||||
|
|
||||||
// Press
|
// Press
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(innerKey)), pointer: 1);
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(innerKey)), pointer: 1);
|
||||||
@ -1019,7 +1019,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)));
|
||||||
|
|
||||||
// Press middle
|
// Press middle
|
||||||
await tester.startGesture(tester.getTopLeft(find.byKey(middleKey)) + const Offset(1, 1), pointer: 1);
|
await tester.startGesture(tester.getTopLeft(find.byKey(middleKey)) + const Offset(1, 1), pointer: 1);
|
||||||
@ -1079,7 +1079,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byKey(leftKey)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byKey(leftKey)));
|
||||||
|
|
||||||
final Offset parentPosition = tester.getTopLeft(find.byKey(parentKey)) + const Offset(1, 1);
|
final Offset parentPosition = tester.getTopLeft(find.byKey(parentKey)) + const Offset(1, 1);
|
||||||
|
|
||||||
@ -1191,7 +1191,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)));
|
||||||
|
|
||||||
// Press inner
|
// Press inner
|
||||||
final TestGesture gesture = await tester.startGesture(const Offset(100, 50), pointer: 1);
|
final TestGesture gesture = await tester.startGesture(const Offset(100, 50), pointer: 1);
|
||||||
@ -1265,7 +1265,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byKey(innerKey)));
|
||||||
|
|
||||||
// Press
|
// Press
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(innerKey)), pointer: 1);
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(innerKey)), pointer: 1);
|
||||||
|
@ -1006,7 +1006,7 @@ void main() {
|
|||||||
child: SizedBox(key: sizedBoxKey, width: 20, height: 20),
|
child: SizedBox(key: sizedBoxKey, width: 20, height: 20),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
final MaterialInkController controller = Material.of(sizedBoxKey.currentContext!)!;
|
final MaterialInkController controller = Material.of(sizedBoxKey.currentContext!);
|
||||||
|
|
||||||
final TrackPaintInkFeature tracker = TrackPaintInkFeature(
|
final TrackPaintInkFeature tracker = TrackPaintInkFeature(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
@ -1015,7 +1015,7 @@ void main() {
|
|||||||
controller.addInkFeature(tracker);
|
controller.addInkFeature(tracker);
|
||||||
expect(tracker.paintCount, 0);
|
expect(tracker.paintCount, 0);
|
||||||
|
|
||||||
// Force a repaint. Since it's offstage, the ink feture should not get painted.
|
// Force a repaint. Since it's offstage, the ink feature should not get painted.
|
||||||
materialKey.currentContext!.findRenderObject()!.paint(PaintingContext(ContainerLayer(), Rect.largest), Offset.zero);
|
materialKey.currentContext!.findRenderObject()!.paint(PaintingContext(ContainerLayer(), Rect.largest), Offset.zero);
|
||||||
expect(tracker.paintCount, 0);
|
expect(tracker.paintCount, 0);
|
||||||
|
|
||||||
|
@ -1442,7 +1442,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
@ -1453,7 +1453,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
|
@ -32,7 +32,7 @@ void main() {
|
|||||||
await tester.tap(find.text('BUTTON'));
|
await tester.tap(find.text('BUTTON'));
|
||||||
await tester.pump(const Duration(milliseconds: 10));
|
await tester.pump(const Duration(milliseconds: 10));
|
||||||
|
|
||||||
final RenderBox splash = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox splash = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
expect(splash, paints..circle(color: splashColor));
|
expect(splash, paints..circle(color: splashColor));
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
@ -72,7 +72,7 @@ void main() {
|
|||||||
await tester.pump(const Duration(milliseconds: 10));
|
await tester.pump(const Duration(milliseconds: 10));
|
||||||
|
|
||||||
if (!kIsWeb) {
|
if (!kIsWeb) {
|
||||||
final RenderBox splash = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox splash = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
expect(splash, paints..circle(color: splashColor));
|
expect(splash, paints..circle(color: splashColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ void main() {
|
|||||||
await tester.sendKeyEvent(LogicalKeyboardKey.space);
|
await tester.sendKeyEvent(LogicalKeyboardKey.space);
|
||||||
await tester.pump(const Duration(milliseconds: 10));
|
await tester.pump(const Duration(milliseconds: 10));
|
||||||
|
|
||||||
final RenderBox splash = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox splash = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
expect(splash, paints..circle(color: splashColor));
|
expect(splash, paints..circle(color: splashColor));
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
@ -195,7 +195,7 @@ void main() {
|
|||||||
await tester.pump(); // start gesture
|
await tester.pump(); // start gesture
|
||||||
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
||||||
|
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
// centered in material button.
|
// centered in material button.
|
||||||
expect(box, paints..circle(x: 44.0, y: 18.0, color: splashColor));
|
expect(box, paints..circle(x: 44.0, y: 18.0, color: splashColor));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
@ -226,7 +226,7 @@ void main() {
|
|||||||
final TestGesture gesture = await tester.startGesture(top);
|
final TestGesture gesture = await tester.startGesture(top);
|
||||||
await tester.pump(); // start gesture
|
await tester.pump(); // start gesture
|
||||||
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
// paints above material
|
// paints above material
|
||||||
expect(box, paints..circle(x: 44.0, y: 0.0, color: splashColor));
|
expect(box, paints..circle(x: 44.0, y: 0.0, color: splashColor));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
@ -326,7 +326,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
expect(box, isNot(paints..rect(color: focusColor)));
|
expect(box, isNot(paints..rect(color: focusColor)));
|
||||||
|
|
||||||
focusNode.requestFocus();
|
focusNode.requestFocus();
|
||||||
@ -425,7 +425,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
|
final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||||
await gesture.addPointer();
|
await gesture.addPointer();
|
||||||
expect(box, isNot(paints..rect(color: hoverColor)));
|
expect(box, isNot(paints..rect(color: hoverColor)));
|
||||||
|
@ -1000,7 +1000,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
// 5 tick marks and a thumb.
|
// 5 tick marks and a thumb.
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 6));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 6));
|
||||||
@ -1056,7 +1056,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> testReparenting(bool reparent) async {
|
Future<void> testReparenting(bool reparent) async {
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
final Offset center = tester.getCenter(find.byType(Slider));
|
final Offset center = tester.getCenter(find.byType(Slider));
|
||||||
// Move to 0.0.
|
// Move to 0.0.
|
||||||
TestGesture gesture = await tester.startGesture(Offset.zero);
|
TestGesture gesture = await tester.startGesture(Offset.zero);
|
||||||
@ -2030,7 +2030,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildApp());
|
await tester.pumpWidget(buildApp());
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
// Check that thumb color is using active color.
|
// Check that thumb color is using active color.
|
||||||
expect(material, paints..circle(color: activeColor));
|
expect(material, paints..circle(color: activeColor));
|
||||||
|
|
||||||
@ -2989,7 +2989,7 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final MaterialInkController material =
|
final MaterialInkController material =
|
||||||
Material.of(tester.element(find.byType(Slider)))!;
|
Material.of(tester.element(find.byType(Slider)));
|
||||||
expect(material, paints..circle(color: color));
|
expect(material, paints..circle(color: color));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3012,7 +3012,7 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final MaterialInkController material =
|
final MaterialInkController material =
|
||||||
Material.of(tester.element(find.byType(Slider)))!;
|
Material.of(tester.element(find.byType(Slider)));
|
||||||
expect(material, paints..circle(color: color));
|
expect(material, paints..circle(color: color));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3032,7 +3032,7 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final MaterialInkController material =
|
final MaterialInkController material =
|
||||||
Material.of(tester.element(find.byType(CupertinoSlider)))!;
|
Material.of(tester.element(find.byType(CupertinoSlider)));
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints
|
paints
|
||||||
@ -3064,7 +3064,7 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final MaterialInkController material =
|
final MaterialInkController material =
|
||||||
Material.of(tester.element(find.byType(CupertinoSlider)))!;
|
Material.of(tester.element(find.byType(CupertinoSlider)));
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints..rrect()..rrect()..rrect()..rrect()..rrect()..rrect(color: color),
|
paints..rrect()..rrect()..rrect()..rrect()..rrect()..rrect(color: color),
|
||||||
|
@ -163,7 +163,7 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(buildApp());
|
await tester.pumpWidget(buildApp());
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
||||||
|
|
||||||
// Check default theme for enabled widget.
|
// Check default theme for enabled widget.
|
||||||
@ -356,7 +356,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, secondaryTrackValue: 0.75, enabled: false));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, secondaryTrackValue: 0.75, enabled: false));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
@ -380,7 +380,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, secondaryTrackValue: 0.75, enabled: false));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, secondaryTrackValue: 0.75, enabled: false));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
@ -487,7 +487,7 @@ void main() {
|
|||||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, secondaryTrackValue: 0.5));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25, secondaryTrackValue: 0.5));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
const Radius radius = Radius.circular(2);
|
const Radius radius = Radius.circular(2);
|
||||||
const Radius activatedRadius = Radius.circular(3);
|
const Radius activatedRadius = Radius.circular(3);
|
||||||
@ -523,7 +523,7 @@ void main() {
|
|||||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
// With no touch, paints only the thumb.
|
// With no touch, paints only the thumb.
|
||||||
expect(
|
expect(
|
||||||
@ -643,7 +643,7 @@ void main() {
|
|||||||
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
final SliderThemeData sliderTheme = theme.sliderTheme.copyWith(thumbColor: Colors.red.shade500);
|
||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.45));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
expect(material, paints..circle(color: sliderTheme.thumbColor, radius: 10.0));
|
expect(material, paints..circle(color: sliderTheme.thumbColor, radius: 10.0));
|
||||||
|
|
||||||
@ -1050,7 +1050,7 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
// Top and bottom are centerY (300) + and - trackRadius (8).
|
// Top and bottom are centerY (300) + and - trackRadius (8).
|
||||||
expect(
|
expect(
|
||||||
@ -1082,7 +1082,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
@ -1106,7 +1106,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.25));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
@ -1132,7 +1132,7 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, divisions: 2));
|
await tester.pumpWidget(_buildApp(sliderTheme, value: 0.5, divisions: 2));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
@ -1168,7 +1168,7 @@ void main() {
|
|||||||
await tester.startGesture(center);
|
await tester.startGesture(center);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
expect(
|
expect(
|
||||||
material,
|
material,
|
||||||
paints..circle(
|
paints..circle(
|
||||||
@ -1190,7 +1190,7 @@ void main() {
|
|||||||
|
|
||||||
final MaterialInkController material = Material.of(
|
final MaterialInkController material = Material.of(
|
||||||
tester.element(find.byType(Slider)),
|
tester.element(find.byType(Slider)),
|
||||||
)!;
|
);
|
||||||
|
|
||||||
// The track rectangle begins at 10 pixels from the left of the screen and ends 10 pixels from the right
|
// The track rectangle begins at 10 pixels from the left of the screen and ends 10 pixels from the right
|
||||||
// (790 pixels from the left). The main check here it that the track itself should be centered on
|
// (790 pixels from the left). The main check here it that the track itself should be centered on
|
||||||
@ -1242,7 +1242,7 @@ void main() {
|
|||||||
divisions: 4,
|
divisions: 4,
|
||||||
));
|
));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
expect(material, paintsExactlyCountTimes(#drawRect, 0));
|
expect(material, paintsExactlyCountTimes(#drawRect, 0));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
||||||
@ -1262,7 +1262,7 @@ void main() {
|
|||||||
divisions: 4,
|
divisions: 4,
|
||||||
));
|
));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
// Only 2 track segments.
|
// Only 2 track segments.
|
||||||
expect(material, paintsExactlyCountTimes(#drawRRect, 2));
|
expect(material, paintsExactlyCountTimes(#drawRRect, 2));
|
||||||
@ -1286,7 +1286,7 @@ void main() {
|
|||||||
divisions: 4,
|
divisions: 4,
|
||||||
));
|
));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
// Only 5 tick marks.
|
// Only 5 tick marks.
|
||||||
expect(material, paintsExactlyCountTimes(#drawRect, 0));
|
expect(material, paintsExactlyCountTimes(#drawRect, 0));
|
||||||
@ -1309,7 +1309,7 @@ void main() {
|
|||||||
divisions: 4,
|
divisions: 4,
|
||||||
));
|
));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
// Only 1 thumb.
|
// Only 1 thumb.
|
||||||
expect(material, paintsExactlyCountTimes(#drawRect, 0));
|
expect(material, paintsExactlyCountTimes(#drawRect, 0));
|
||||||
@ -1333,7 +1333,7 @@ void main() {
|
|||||||
divisions: 4,
|
divisions: 4,
|
||||||
));
|
));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
|
|
||||||
// Tap the center of the track and wait for animations to finish.
|
// Tap the center of the track and wait for animations to finish.
|
||||||
final Offset center = tester.getCenter(find.byType(Slider));
|
final Offset center = tester.getCenter(find.byType(Slider));
|
||||||
@ -1362,7 +1362,7 @@ void main() {
|
|||||||
divisions: 4,
|
divisions: 4,
|
||||||
));
|
));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
||||||
|
|
||||||
// Tap the center of the track and wait for animations to finish.
|
// Tap the center of the track and wait for animations to finish.
|
||||||
@ -1393,7 +1393,7 @@ void main() {
|
|||||||
divisions: 4,
|
divisions: 4,
|
||||||
));
|
));
|
||||||
|
|
||||||
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)))!;
|
final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
|
||||||
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
|
||||||
|
|
||||||
// Tap the center of the track to kick off the animation of the value indicator.
|
// Tap the center of the track to kick off the animation of the value indicator.
|
||||||
|
@ -364,7 +364,7 @@ void main() {
|
|||||||
expect(find.text('A'), findsOneWidget);
|
expect(find.text('A'), findsOneWidget);
|
||||||
expect(find.text('B'), findsOneWidget);
|
expect(find.text('B'), findsOneWidget);
|
||||||
expect(find.text('C'), findsOneWidget);
|
expect(find.text('C'), findsOneWidget);
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('A')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('A')));
|
||||||
expect(controller, isNotNull);
|
expect(controller, isNotNull);
|
||||||
expect(controller.index, 2);
|
expect(controller.index, 2);
|
||||||
expect(controller.previousIndex, 2);
|
expect(controller.previousIndex, 2);
|
||||||
@ -400,7 +400,7 @@ void main() {
|
|||||||
expect(find.text('A'), findsOneWidget);
|
expect(find.text('A'), findsOneWidget);
|
||||||
expect(find.text('B'), findsOneWidget);
|
expect(find.text('B'), findsOneWidget);
|
||||||
expect(find.text('C'), findsOneWidget);
|
expect(find.text('C'), findsOneWidget);
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('A')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('A')));
|
||||||
expect(controller.index, 2);
|
expect(controller.index, 2);
|
||||||
expect(controller.previousIndex, 2);
|
expect(controller.previousIndex, 2);
|
||||||
|
|
||||||
@ -421,7 +421,7 @@ void main() {
|
|||||||
final List<String> tabs = <String>['AAAAAA', 'BBBBBB', 'CCCCCC', 'DDDDDD', 'EEEEEE', 'FFFFFF', 'GGGGGG', 'HHHHHH', 'IIIIII', 'JJJJJJ', 'KKKKKK', 'LLLLLL'];
|
final List<String> tabs = <String>['AAAAAA', 'BBBBBB', 'CCCCCC', 'DDDDDD', 'EEEEEE', 'FFFFFF', 'GGGGGG', 'HHHHHH', 'IIIIII', 'JJJJJJ', 'KKKKKK', 'LLLLLL'];
|
||||||
const Key tabBarKey = Key('TabBar');
|
const Key tabBarKey = Key('TabBar');
|
||||||
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'AAAAAA', isScrollable: true, tabBarKey: tabBarKey));
|
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'AAAAAA', isScrollable: true, tabBarKey: tabBarKey));
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')));
|
||||||
expect(controller, isNotNull);
|
expect(controller, isNotNull);
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
@ -442,7 +442,7 @@ void main() {
|
|||||||
const Key tabBarKey = Key('TabBar');
|
const Key tabBarKey = Key('TabBar');
|
||||||
const EdgeInsetsGeometry padding = EdgeInsets.only(right: 30, left: 60);
|
const EdgeInsetsGeometry padding = EdgeInsets.only(right: 30, left: 60);
|
||||||
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'AAAAAA', isScrollable: true, tabBarKey: tabBarKey, padding: padding));
|
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'AAAAAA', isScrollable: true, tabBarKey: tabBarKey, padding: padding));
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')));
|
||||||
expect(controller, isNotNull);
|
expect(controller, isNotNull);
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
@ -470,7 +470,7 @@ void main() {
|
|||||||
padding: padding,
|
padding: padding,
|
||||||
textDirection: TextDirection.rtl,
|
textDirection: TextDirection.rtl,
|
||||||
));
|
));
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')));
|
||||||
expect(controller, isNotNull);
|
expect(controller, isNotNull);
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
@ -489,7 +489,7 @@ void main() {
|
|||||||
final List<String> tabs = <String>['AAAA', 'BBBB', 'CCCC', 'DDDD', 'EEEE', 'FFFF', 'GGGG', 'HHHH', 'IIII', 'JJJJ', 'KKKK', 'LLLL'];
|
final List<String> tabs = <String>['AAAA', 'BBBB', 'CCCC', 'DDDD', 'EEEE', 'FFFF', 'GGGG', 'HHHH', 'IIII', 'JJJJ', 'KKKK', 'LLLL'];
|
||||||
const Key tabBarKey = Key('TabBar');
|
const Key tabBarKey = Key('TabBar');
|
||||||
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'AAAA', isScrollable: true, tabBarKey: tabBarKey));
|
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'AAAA', isScrollable: true, tabBarKey: tabBarKey));
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAA')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAA')));
|
||||||
expect(controller, isNotNull);
|
expect(controller, isNotNull);
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await tester.pumpWidget(builder());
|
await tester.pumpWidget(builder());
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('AAAAAA')));
|
||||||
|
|
||||||
TestGesture gesture = await tester.startGesture(tester.getCenter(find.text(tabs[0])));
|
TestGesture gesture = await tester.startGesture(tester.getCenter(find.text(tabs[0])));
|
||||||
await gesture.moveBy(const Offset(-600.0, 0.0));
|
await gesture.moveBy(const Offset(-600.0, 0.0));
|
||||||
@ -586,7 +586,7 @@ void main() {
|
|||||||
expect(find.text('LEFT CHILD'), findsOneWidget);
|
expect(find.text('LEFT CHILD'), findsOneWidget);
|
||||||
expect(find.text('RIGHT CHILD'), findsNothing);
|
expect(find.text('RIGHT CHILD'), findsNothing);
|
||||||
|
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')));
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
// Fling to the left, switch from the 'LEFT' tab to the 'RIGHT'
|
// Fling to the left, switch from the 'LEFT' tab to the 'RIGHT'
|
||||||
@ -615,7 +615,7 @@ void main() {
|
|||||||
expect(find.text('LEFT CHILD'), findsOneWidget);
|
expect(find.text('LEFT CHILD'), findsOneWidget);
|
||||||
expect(find.text('RIGHT CHILD'), findsNothing);
|
expect(find.text('RIGHT CHILD'), findsNothing);
|
||||||
|
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')));
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
final Offset flingStart = tester.getCenter(find.text('LEFT CHILD'));
|
final Offset flingStart = tester.getCenter(find.text('LEFT CHILD'));
|
||||||
@ -636,7 +636,7 @@ void main() {
|
|||||||
expect(find.text('LEFT CHILD'), findsOneWidget);
|
expect(find.text('LEFT CHILD'), findsOneWidget);
|
||||||
expect(find.text('RIGHT CHILD'), findsNothing);
|
expect(find.text('RIGHT CHILD'), findsNothing);
|
||||||
|
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')));
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
final Offset flingStart = tester.getCenter(find.text('LEFT CHILD'));
|
final Offset flingStart = tester.getCenter(find.text('LEFT CHILD'));
|
||||||
@ -659,7 +659,7 @@ void main() {
|
|||||||
expect(find.text('LEFT CHILD'), findsOneWidget);
|
expect(find.text('LEFT CHILD'), findsOneWidget);
|
||||||
expect(find.text('RIGHT CHILD'), findsNothing);
|
expect(find.text('RIGHT CHILD'), findsNothing);
|
||||||
|
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')));
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
final Offset flingStart = tester.getCenter(find.text('LEFT CHILD'));
|
final Offset flingStart = tester.getCenter(find.text('LEFT CHILD'));
|
||||||
@ -772,7 +772,7 @@ void main() {
|
|||||||
final List<String> tabs = <String>['LEFT', 'RIGHT'];
|
final List<String> tabs = <String>['LEFT', 'RIGHT'];
|
||||||
|
|
||||||
await tester.pumpWidget(buildLeftRightApp(tabs: tabs, value: 'LEFT'));
|
await tester.pumpWidget(buildLeftRightApp(tabs: tabs, value: 'LEFT'));
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('LEFT')));
|
||||||
|
|
||||||
expect(controller, isNotNull);
|
expect(controller, isNotNull);
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
@ -1013,7 +1013,7 @@ void main() {
|
|||||||
final List<String> tabs = <String>['A', 'B', 'C'];
|
final List<String> tabs = <String>['A', 'B', 'C'];
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'B', animationDuration: animationDuration));
|
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'B', animationDuration: animationDuration));
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('A')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('A')));
|
||||||
|
|
||||||
await tester.tap(find.text('A'));
|
await tester.tap(find.text('A'));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
@ -1241,7 +1241,7 @@ void main() {
|
|||||||
final List<String> tabs = <String>['A', 'B', 'C'];
|
final List<String> tabs = <String>['A', 'B', 'C'];
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'B', animationDuration: Duration.zero));
|
await tester.pumpWidget(buildFrame(tabs: tabs, value: 'B', animationDuration: Duration.zero));
|
||||||
final TabController controller = DefaultTabController.of(tester.element(find.text('A')))!;
|
final TabController controller = DefaultTabController.of(tester.element(find.text('A')));
|
||||||
|
|
||||||
await tester.tap(find.text('A'));
|
await tester.tap(find.text('A'));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
@ -1288,7 +1288,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await tester.pumpWidget(buildWithTabBarView());
|
await tester.pumpWidget(buildWithTabBarView());
|
||||||
TabController controller = DefaultTabController.of(tester.element(find.text('A')))!;
|
TabController controller = DefaultTabController.of(tester.element(find.text('A')));
|
||||||
expect(controller.index, 0);
|
expect(controller.index, 0);
|
||||||
|
|
||||||
tabs.add('B');
|
tabs.add('B');
|
||||||
@ -1297,7 +1297,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildWithTabBarView());
|
await tester.pumpWidget(buildWithTabBarView());
|
||||||
await tester.tap(find.text('C'));
|
await tester.tap(find.text('C'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
controller = DefaultTabController.of(tester.element(find.text('A')))!;
|
controller = DefaultTabController.of(tester.element(find.text('A')));
|
||||||
expect(controller.index, 2);
|
expect(controller.index, 2);
|
||||||
|
|
||||||
expect(tester.takeException(), isNull);
|
expect(tester.takeException(), isNull);
|
||||||
@ -3752,7 +3752,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TabController getController() => DefaultTabController.of(tester.element(find.text('A')))!;
|
TabController getController() => DefaultTabController.of(tester.element(find.text('A')));
|
||||||
|
|
||||||
await tester.pumpWidget(buildTabs(threeTabs));
|
await tester.pumpWidget(buildTabs(threeTabs));
|
||||||
await tester.tap(find.text('B'));
|
await tester.tap(find.text('B'));
|
||||||
@ -4346,7 +4346,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
TabController getController() => DefaultTabController.of(tester.element(find.text('B')))!;
|
TabController getController() => DefaultTabController.of(tester.element(find.text('B')));
|
||||||
TabController controller = getController();
|
TabController controller = getController();
|
||||||
|
|
||||||
controller.animateTo(2, duration: const Duration(milliseconds: 200), curve: Curves.linear);
|
controller.animateTo(2, duration: const Duration(milliseconds: 200), curve: Curves.linear);
|
||||||
|
@ -1249,7 +1249,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 0));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
@ -1260,7 +1260,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
||||||
{
|
{
|
||||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
expect(material, paintsExactlyCountTimes(#drawCircle, 1));
|
||||||
await gesture.up();
|
await gesture.up();
|
||||||
|
@ -116,7 +116,7 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(Builder(
|
await tester.pumpWidget(Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
textHeightBehavior = DefaultTextHeightBehavior.of(context);
|
textHeightBehavior = DefaultTextHeightBehavior.maybeOf(context);
|
||||||
return textWidget;
|
return textWidget;
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
@ -286,8 +286,8 @@ class _TestState extends State<Test> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_beforeController.setParent(PrimaryScrollController.of(context));
|
_beforeController.setParent(PrimaryScrollController.maybeOf(context));
|
||||||
_afterController.setParent(PrimaryScrollController.of(context));
|
_afterController.setParent(PrimaryScrollController.maybeOf(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -215,7 +215,7 @@ void main() {
|
|||||||
await tester.pumpWidget(buildFrame());
|
await tester.pumpWidget(buildFrame());
|
||||||
expect(find.text('top'), findsOneWidget);
|
expect(find.text('top'), findsOneWidget);
|
||||||
|
|
||||||
final ScrollPosition position = Scrollable.of(tester.element(find.text('middle')))!.position;
|
final ScrollPosition position = Scrollable.of(tester.element(find.text('middle'))).position;
|
||||||
expect(position.viewportDimension, 600.0);
|
expect(position.viewportDimension, 600.0);
|
||||||
expect(position.pixels, 0.0);
|
expect(position.pixels, 0.0);
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ void main() {
|
|||||||
home: StatefulBuilder(
|
home: StatefulBuilder(
|
||||||
key: builderKey,
|
key: builderKey,
|
||||||
builder: (BuildContext context, StateSetter setter) {
|
builder: (BuildContext context, StateSetter setter) {
|
||||||
PageStorage.of(context)!.writeState(context, storedValue);
|
PageStorage.of(context).writeState(context, storedValue);
|
||||||
setState = setter;
|
setState = setter;
|
||||||
return Center(
|
return Center(
|
||||||
child: Text('storedValue: $storedValue'),
|
child: Text('storedValue: $storedValue'),
|
||||||
@ -28,13 +28,13 @@ void main() {
|
|||||||
|
|
||||||
final Element builderElement = tester.element(find.byKey(builderKey));
|
final Element builderElement = tester.element(find.byKey(builderKey));
|
||||||
expect(PageStorage.of(builderElement), isNotNull);
|
expect(PageStorage.of(builderElement), isNotNull);
|
||||||
expect(PageStorage.of(builderElement)!.readState(builderElement), equals(storedValue));
|
expect(PageStorage.of(builderElement).readState(builderElement), equals(storedValue));
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
storedValue = 1;
|
storedValue = 1;
|
||||||
});
|
});
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(PageStorage.of(builderElement)!.readState(builderElement), equals(storedValue));
|
expect(PageStorage.of(builderElement).readState(builderElement), equals(storedValue));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('PageStorage read and write by identifier', (WidgetTester tester) async {
|
testWidgets('PageStorage read and write by identifier', (WidgetTester tester) async {
|
||||||
@ -46,7 +46,7 @@ void main() {
|
|||||||
home: StatefulBuilder(
|
home: StatefulBuilder(
|
||||||
key: key,
|
key: key,
|
||||||
builder: (BuildContext context, StateSetter setter) {
|
builder: (BuildContext context, StateSetter setter) {
|
||||||
PageStorage.of(context)!.writeState(context, storedValue, identifier: 123);
|
PageStorage.of(context).writeState(context, storedValue, identifier: 123);
|
||||||
setState = setter;
|
setState = setter;
|
||||||
return Center(
|
return Center(
|
||||||
child: Text('storedValue: $storedValue'),
|
child: Text('storedValue: $storedValue'),
|
||||||
@ -60,8 +60,8 @@ void main() {
|
|||||||
await tester.pumpWidget(buildWidthKey(key));
|
await tester.pumpWidget(buildWidthKey(key));
|
||||||
Element builderElement = tester.element(find.byKey(key));
|
Element builderElement = tester.element(find.byKey(key));
|
||||||
expect(PageStorage.of(builderElement), isNotNull);
|
expect(PageStorage.of(builderElement), isNotNull);
|
||||||
expect(PageStorage.of(builderElement)!.readState(builderElement), isNull);
|
expect(PageStorage.of(builderElement).readState(builderElement), isNull);
|
||||||
expect(PageStorage.of(builderElement)!.readState(builderElement, identifier: 123), equals(storedValue));
|
expect(PageStorage.of(builderElement).readState(builderElement, identifier: 123), equals(storedValue));
|
||||||
|
|
||||||
// New StatefulBuilder widget - different key - but the same PageStorage identifier.
|
// New StatefulBuilder widget - different key - but the same PageStorage identifier.
|
||||||
|
|
||||||
@ -69,14 +69,14 @@ void main() {
|
|||||||
await tester.pumpWidget(buildWidthKey(key));
|
await tester.pumpWidget(buildWidthKey(key));
|
||||||
builderElement = tester.element(find.byKey(key));
|
builderElement = tester.element(find.byKey(key));
|
||||||
expect(PageStorage.of(builderElement), isNotNull);
|
expect(PageStorage.of(builderElement), isNotNull);
|
||||||
expect(PageStorage.of(builderElement)!.readState(builderElement), isNull);
|
expect(PageStorage.of(builderElement).readState(builderElement), isNull);
|
||||||
expect(PageStorage.of(builderElement)!.readState(builderElement, identifier: 123), equals(storedValue));
|
expect(PageStorage.of(builderElement).readState(builderElement, identifier: 123), equals(storedValue));
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
storedValue = 1;
|
storedValue = 1;
|
||||||
});
|
});
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(PageStorage.of(builderElement)!.readState(builderElement, identifier: 123), equals(storedValue));
|
expect(PageStorage.of(builderElement).readState(builderElement, identifier: 123), equals(storedValue));
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ class BucketSpyState extends State<BucketSpy> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
bucket = RestorationScope.of(context);
|
bucket = RestorationScope.maybeOf(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -22,11 +22,11 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
T findPhysics<T extends ScrollPhysics>(WidgetTester tester) {
|
T findPhysics<T extends ScrollPhysics>(WidgetTester tester) {
|
||||||
return Scrollable.of(find.byType(TestWidget).evaluate().first)!.position.physics as T;
|
return Scrollable.of(find.byType(TestWidget).evaluate().first).position.physics as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollMetrics findMetrics(WidgetTester tester) {
|
ScrollMetrics findMetrics(WidgetTester tester) {
|
||||||
return Scrollable.of(find.byType(TestWidget).evaluate().first)!.position;
|
return Scrollable.of(find.byType(TestWidget).evaluate().first).position;
|
||||||
}
|
}
|
||||||
|
|
||||||
testWidgets('ScrollAwareImageProvider does not delay if widget is not in scrollable', (WidgetTester tester) async {
|
testWidgets('ScrollAwareImageProvider does not delay if widget is not in scrollable', (WidgetTester tester) async {
|
||||||
|
@ -50,7 +50,7 @@ void main() {
|
|||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
behavior = ScrollConfiguration.of(context) as TestScrollBehavior;
|
behavior = ScrollConfiguration.of(context) as TestScrollBehavior;
|
||||||
position = Scrollable.of(context)!.position as ScrollPositionWithSingleContext;
|
position = Scrollable.of(context).position as ScrollPositionWithSingleContext;
|
||||||
return Container(height: 1000.0);
|
return Container(height: 1000.0);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -218,7 +218,7 @@ void main() {
|
|||||||
ScrollNotificationObserver(
|
ScrollNotificationObserver(
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
observer = ScrollNotificationObserver.of(context)!;
|
observer = ScrollNotificationObserver.of(context);
|
||||||
return const SingleChildScrollView(
|
return const SingleChildScrollView(
|
||||||
child: SizedBox(height: 1200.0),
|
child: SizedBox(height: 1200.0),
|
||||||
);
|
);
|
||||||
|
@ -1478,7 +1478,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
final ScrollController controller = PrimaryScrollController.of(
|
final ScrollController controller = PrimaryScrollController.of(
|
||||||
tester.element(find.byType(CustomScrollView)),
|
tester.element(find.byType(CustomScrollView)),
|
||||||
)!;
|
);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.position.pixels, equals(0.0));
|
expect(controller.position.pixels, equals(0.0));
|
||||||
expect(
|
expect(
|
||||||
|
@ -22,7 +22,7 @@ class _ScrollPositionListenerState extends State<ScrollPositionListener> {
|
|||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_position?.removeListener(listener);
|
_position?.removeListener(listener);
|
||||||
_position = Scrollable.of(context)?.position;
|
_position = Scrollable.maybeOf(context)?.position;
|
||||||
_position?.addListener(listener);
|
_position?.addListener(listener);
|
||||||
widget.log('didChangeDependencies ${_position?.pixels.toStringAsFixed(1)}');
|
widget.log('didChangeDependencies ${_position?.pixels.toStringAsFixed(1)}');
|
||||||
}
|
}
|
||||||
|
@ -941,7 +941,7 @@ void main() {
|
|||||||
// Getting the tester to simulate a life-like fling is difficult.
|
// Getting the tester to simulate a life-like fling is difficult.
|
||||||
// Instead, just manually drive the activity with a ballistic simulation as
|
// Instead, just manually drive the activity with a ballistic simulation as
|
||||||
// if the user has flung the list.
|
// if the user has flung the list.
|
||||||
Scrollable.of(find.byType(SizedBox).evaluate().first)!.position.activity!.delegate.goBallistic(4000);
|
Scrollable.of(find.byType(SizedBox).evaluate().first).position.activity!.delegate.goBallistic(4000);
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(find.byKey(const ValueKey<String>('Box 0')), findsNothing);
|
expect(find.byKey(const ValueKey<String>('Box 0')), findsNothing);
|
||||||
@ -970,7 +970,7 @@ void main() {
|
|||||||
));
|
));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final ScrollPosition position = Scrollable.of(find.byType(SizedBox).evaluate().first)!.position;
|
final ScrollPosition position = Scrollable.of(find.byType(SizedBox).evaluate().first).position;
|
||||||
final SuperPessimisticScrollPhysics physics = position.physics as SuperPessimisticScrollPhysics;
|
final SuperPessimisticScrollPhysics physics = position.physics as SuperPessimisticScrollPhysics;
|
||||||
|
|
||||||
expect(find.byKey(const ValueKey<String>('Box 0')), findsOneWidget);
|
expect(find.byKey(const ValueKey<String>('Box 0')), findsOneWidget);
|
||||||
@ -1014,7 +1014,7 @@ void main() {
|
|||||||
));
|
));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final ScrollPosition position = Scrollable.of(find.byType(SizedBox).evaluate().first)!.position;
|
final ScrollPosition position = Scrollable.of(find.byType(SizedBox).evaluate().first).position;
|
||||||
|
|
||||||
expect(find.byKey(const ValueKey<String>('Cheap box 0')), findsOneWidget);
|
expect(find.byKey(const ValueKey<String>('Cheap box 0')), findsOneWidget);
|
||||||
expect(find.byKey(const ValueKey<String>('Cheap box 52')), findsNothing);
|
expect(find.byKey(const ValueKey<String>('Cheap box 52')), findsNothing);
|
||||||
|
@ -1028,7 +1028,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
final ScrollController controller = PrimaryScrollController.of(
|
final ScrollController controller = PrimaryScrollController.of(
|
||||||
tester.element(find.byType(ListView)),
|
tester.element(find.byType(ListView)),
|
||||||
)!;
|
);
|
||||||
expect(controller.position.pixels, 0.0);
|
expect(controller.position.pixels, 0.0);
|
||||||
expect(value, isTrue);
|
expect(value, isTrue);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user