From 0ff0affb3a9db746f6335846236f69ee24445f1a Mon Sep 17 00:00:00 2001 From: Aman Verma Date: Tue, 10 May 2022 02:04:07 +0530 Subject: [PATCH] Expose controller for PaginatedDataTable (#100005) --- .../src/material/paginated_data_table.dart | 16 +++- .../material/paginated_data_table_test.dart | 82 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/material/paginated_data_table.dart b/packages/flutter/lib/src/material/paginated_data_table.dart index f79abdbab4..82070fe900 100644 --- a/packages/flutter/lib/src/material/paginated_data_table.dart +++ b/packages/flutter/lib/src/material/paginated_data_table.dart @@ -86,6 +86,8 @@ class PaginatedDataTable extends StatefulWidget { this.arrowHeadColor, required this.source, this.checkboxHorizontalMargin, + this.controller, + this.primary, }) : assert(actions == null || (actions != null && header != null)), assert(columns != null), assert(dragStartBehavior != null), @@ -105,7 +107,11 @@ class PaginatedDataTable extends StatefulWidget { assert(availableRowsPerPage != null && availableRowsPerPage.contains(rowsPerPage)); return true; }()), - assert(source != null); + assert(source != null), + assert(!(controller != null && (primary ?? false)), + 'Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. ' + 'You cannot both set primary to true and pass an explicit controller.', + ); /// The table card's optional header. /// @@ -237,6 +243,12 @@ class PaginatedDataTable extends StatefulWidget { /// Defines the color of the arrow heads in the footer. final Color? arrowHeadColor; + /// {@macro flutter.widgets.scroll_view.controller} + final ScrollController? controller; + + /// {@macro flutter.widgets.scroll_view.primary} + final bool? primary; + @override PaginatedDataTableState createState() => PaginatedDataTableState(); } @@ -501,6 +513,8 @@ class PaginatedDataTableState extends State { ), SingleChildScrollView( scrollDirection: Axis.horizontal, + primary: widget.primary, + controller: widget.controller, dragStartBehavior: widget.dragStartBehavior, child: ConstrainedBox( constraints: BoxConstraints(minWidth: constraints.minWidth), diff --git a/packages/flutter/test/material/paginated_data_table_test.dart b/packages/flutter/test/material/paginated_data_table_test.dart index 43c5ce0711..2c148d8edf 100644 --- a/packages/flutter/test/material/paginated_data_table_test.dart +++ b/packages/flutter/test/material/paginated_data_table_test.dart @@ -398,6 +398,7 @@ void main() { expect(find.text('Rows per page:'), findsOneWidget); expect(tester.getTopLeft(find.text('Rows per page:')).dx, 18.0); // 14 padding in the footer row, 4 padding from the card }); + testWidgets('PaginatedDataTable custom row height', (WidgetTester tester) async { final TestDataSource source = TestDataSource(); @@ -1043,4 +1044,85 @@ void main() { await tester.pumpWidget(buildFrame(overflowBar)); expect(headerX, tester.getTopLeft(find.byType(ElevatedButton)).dx); }); + + testWidgets('PaginatedDataTable can be scrolled using ScrollController', (WidgetTester tester) async { + final TestDataSource source = TestDataSource(); + final ScrollController scrollController = ScrollController(); + + Widget buildTable(TestDataSource source) { + return Align( + alignment: Alignment.topLeft, + child: SizedBox( + width: 100, + child: PaginatedDataTable( + controller: scrollController, + header: const Text('Test table'), + source: source, + rowsPerPage: 2, + columns: const [ + DataColumn( + label: Text('Name'), + tooltip: 'Name', + ), + DataColumn( + label: Text('Calories'), + tooltip: 'Calories', + numeric: true, + ), + DataColumn( + label: Text('Generation'), + tooltip: 'Generation', + ), + ], + ), + ), + ); + } + + await tester.pumpWidget(MaterialApp( + home: buildTable(source), + )); + + // DataTable uses provided ScrollController + final Scrollable bodyScrollView = tester.widget(find.byType(Scrollable).first); + expect(bodyScrollView.controller, scrollController); + + expect(scrollController.offset, 0.0); + scrollController.jumpTo(50.0); + await tester.pumpAndSettle(); + + expect(scrollController.offset, 50.0); + }); + + testWidgets('PaginatedDataTable uses PrimaryScrollController when primary ', (WidgetTester tester) async { + final ScrollController primaryScrollController = ScrollController(); + final TestDataSource source = TestDataSource(); + + await tester.pumpWidget( + MaterialApp( + home: PrimaryScrollController( + controller: primaryScrollController, + child: PaginatedDataTable( + primary: true, + header: const Text('Test table'), + source: source, + rowsPerPage: 2, + columns: const [ + DataColumn(label: Text('Name')), + DataColumn(label: Text('Calories'), numeric: true), + DataColumn(label: Text('Generation')), + ], + ), + ), + ) + ); + + // DataTable uses primaryScrollController + final Scrollable bodyScrollView = tester.widget(find.byType(Scrollable).first); + expect(bodyScrollView.controller, primaryScrollController); + + // Footer does not use primaryScrollController + final Scrollable footerScrollView = tester.widget(find.byType(Scrollable).last); + expect(footerScrollView.controller, null); + }); }