From 5ae9c913caf5476e9f15cf726487bf6db42f5f5c Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Wed, 12 May 2021 21:13:30 +0200 Subject: [PATCH 1/5] Null Safety --- analysis_options.yaml | 1 + example/lib/examples/layout.dart | 6 +- example/lib/examples/list.dart | 38 +-- example/lib/examples/multi.dart | 2 +- example/lib/main.dart | 12 +- example/pubspec.lock | 110 +++---- example/pubspec.yaml | 2 +- example/test/widget_test.dart | 2 +- lib/data/classes/details.dart | 4 +- lib/templates/3-column/common/details.dart | 22 +- .../3-column/common/section_list.dart | 18 +- lib/templates/3-column/common/sections.dart | 10 +- .../3-column/three_column_navigation.dart | 170 ++++++----- lib/templates/layout/scaffold.dart | 63 ++-- lib/templates/list/responsive_list.dart | 69 +++-- lib/templates/list/views/mobile.dart | 114 +++---- lib/templates/list/views/tablet.dart | 277 +++++++++--------- pubspec.lock | 107 +++---- pubspec.yaml | 9 +- 19 files changed, 494 insertions(+), 542 deletions(-) create mode 100644 analysis_options.yaml diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..2fcb805 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lint/analysis_options_package.yaml diff --git a/example/lib/examples/layout.dart b/example/lib/examples/layout.dart index e4f0350..cc9e7c7 100644 --- a/example/lib/examples/layout.dart +++ b/example/lib/examples/layout.dart @@ -5,9 +5,9 @@ class LayoutExample extends StatelessWidget { @override Widget build(BuildContext context) { return ResponsiveScaffold( - title: Text('Responsive Layout Example'), + title: const Text('Responsive Layout Example'), drawer: ListView( - children: [ + children: const [ ListTile( leading: Icon(Icons.settings), title: Text('Settings Page'), @@ -65,7 +65,7 @@ class LayoutExample extends StatelessWidget { onPressed: () {}, ), body: Center( - child: RaisedButton( + child: ElevatedButton( child: Text('Close'), onPressed: () { Navigator.pop(context); diff --git a/example/lib/examples/list.dart b/example/lib/examples/list.dart index 3289698..4842eff 100644 --- a/example/lib/examples/list.dart +++ b/example/lib/examples/list.dart @@ -3,7 +3,7 @@ import 'package:responsive_scaffold/responsive_scaffold.dart'; class ListExample extends StatefulWidget { const ListExample({ - Key key, + Key? key, }); @override @@ -11,9 +11,9 @@ class ListExample extends StatefulWidget { } class _ListExampleState extends State { - var _scaffoldKey = new GlobalKey(); + var _scaffoldKey = GlobalKey(); - List _items; + List? _items; @override void initState() { @@ -25,22 +25,22 @@ class _ListExampleState extends State { Widget build(BuildContext context) { return ResponsiveListScaffold.builder( scaffoldKey: _scaffoldKey, - detailBuilder: (BuildContext context, int index, bool tablet) { - final i = _items[index]; + detailBuilder: (BuildContext context, int? index, bool tablet) { + final i = _items![index!]; return DetailsScreen( - body: new ExampleDetailsScreen( + body: ExampleDetailsScreen( items: _items, row: i, tablet: tablet, onDelete: () { setState(() { - _items.removeAt(index); + _items!.removeAt(index); }); if (!tablet) Navigator.of(context).pop(); }, onChanged: (String value) { setState(() { - _items[index] = value; + _items![index] = value; }); }, ), @@ -55,7 +55,7 @@ class _ListExampleState extends State { ], itemCount: _items?.length ?? 0, itemBuilder: (BuildContext context, int index) { - final i = _items[index]; + final i = _items![index]; return ListTile( leading: Text(i), ); @@ -72,7 +72,7 @@ class _ListExampleState extends State { floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { - _scaffoldKey.currentState.showSnackBar(SnackBar( + ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Snackbar!"), )); }, @@ -83,16 +83,16 @@ class _ListExampleState extends State { class ExampleDetailsScreen extends StatelessWidget { const ExampleDetailsScreen({ - Key key, - @required List items, - @required this.row, - @required this.tablet, - @required this.onDelete, - @required this.onChanged, - }) : _items = items, + Key? key, + required List? items, + required this.row, + required this.tablet, + required this.onDelete, + required this.onChanged, + }) : _items = items, super(key: key); - final List _items; + final List? _items; final String row; final bool tablet; final VoidCallback onDelete; @@ -122,7 +122,7 @@ class ExampleDetailsScreen extends StatelessWidget { elevation: 0.0, child: Container( child: IconButton( - icon: Icon(Icons.share), + icon: const Icon(Icons.share), onPressed: () {}, ), ), diff --git a/example/lib/examples/multi.dart b/example/lib/examples/multi.dart index 3430656..47544a4 100644 --- a/example/lib/examples/multi.dart +++ b/example/lib/examples/multi.dart @@ -27,7 +27,7 @@ class MultiColumnNavigationExample extends StatelessWidget { label: Text('All Inboxes'), icon: Icon(Icons.mail), itemCount: 100, - itemBuilder: (context, index, selected) { + itemBuilder: (BuildContext context, int index, bool selected) { return ListTile( leading: CircleAvatar( child: Text(index.toString()), diff --git a/example/lib/main.dart b/example/lib/main.dart index a535598..40a82ea 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -16,7 +16,7 @@ void main() { /// a supported platform (iOS for macOS, Android for Linux and Windows). /// Otherwise, do nothing. void _setTargetPlatformForDesktop() { - TargetPlatform targetPlatform; + TargetPlatform? targetPlatform; if (Platform.isMacOS) { targetPlatform = TargetPlatform.iOS; } else if (Platform.isLinux || Platform.isWindows) { @@ -40,27 +40,27 @@ class MyApp extends StatelessWidget { class HomePage extends StatelessWidget { const HomePage({ - Key key, + Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('Responsive Examples'), + title: const Text('Responsive Examples'), ), body: ListView( children: [ ListTile( - title: Text('Responsive List'), + title: const Text('Responsive List'), onTap: () => _goToScreen(context, ListExample()), ), ListTile( - title: Text('Responsive Layout'), + title: const Text('Responsive Layout'), onTap: () => _goToScreen(context, LayoutExample()), ), ListTile( - title: Text('Multi Column Layout'), + title: const Text('Multi Column Layout'), onTap: () => _goToScreen(context, MultiColumnNavigationExample()), ), ], diff --git a/example/pubspec.lock b/example/pubspec.lock index 80707b1..f29df12 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,62 +1,48 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.2" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" + version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" - charcode: + version: "2.1.0" + characters: dependency: transitive description: - name: charcode + name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" - collection: + version: "1.1.0" + charcode: dependency: transitive description: - name: collection + name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" - convert: + version: "1.2.0" + clock: dependency: transitive description: - name: convert + name: clock url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - crypto: + version: "1.1.0" + collection: dependency: transitive description: - name: crypto + name: collection url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "1.15.0" cupertino_icons: dependency: "direct main" description: @@ -64,6 +50,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.2" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -74,55 +67,27 @@ packages: description: flutter source: sdk version: "0.0.0" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.4" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0+1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" + version: "1.8.0" responsive_scaffold: dependency: "direct dev" description: @@ -136,7 +101,7 @@ packages: name: scroll_to_index url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "2.0.0" sky_engine: dependency: transitive description: flutter @@ -148,62 +113,55 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.5" + version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.11" + version: "0.2.19" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.5.0" + version: "2.1.0" sdks: - dart: ">=2.4.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 30fb5e3..a67dba8 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -3,7 +3,7 @@ description: Demonstrates how to use the responsive_scaffold plugin. publish_to: 'none' environment: - sdk: ">=2.1.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 9977073..7418a4e 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -19,7 +19,7 @@ void main() { expect( find.byWidgetPredicate( (Widget widget) => - widget is Text && widget.data.startsWith('Running on:'), + widget is Text && widget.data!.startsWith('Running on:'), ), findsOneWidget, ); diff --git a/lib/data/classes/details.dart b/lib/data/classes/details.dart index 60afbbd..485425d 100644 --- a/lib/data/classes/details.dart +++ b/lib/data/classes/details.dart @@ -3,9 +3,9 @@ import 'package:flutter/material.dart'; class DetailsScreen { const DetailsScreen({ this.appBar, - @required this.body, + required this.body, }); final Widget body; - final PreferredSizeWidget appBar; + final PreferredSizeWidget? appBar; } diff --git a/lib/templates/3-column/common/details.dart b/lib/templates/3-column/common/details.dart index 891cea5..bf1c834 100644 --- a/lib/templates/3-column/common/details.dart +++ b/lib/templates/3-column/common/details.dart @@ -4,9 +4,9 @@ import '../three_column_navigation.dart'; class DetailsView extends StatelessWidget { const DetailsView({ - Key key, - @required int listIndex, - @required DetailsWidget details, + Key? key, + required int listIndex, + required DetailsWidget details, this.previous, this.next, this.isLast = false, @@ -20,11 +20,11 @@ class DetailsView extends StatelessWidget { final int _listIndex; final DetailsWidget _details; - final VoidCallback previous, next; + final VoidCallback? previous, next; final bool showDetailsArrows; final bool isLast, isFirst; final bool automaticallyImplyLeading; - final GlobalKey scaffoldKey; + final GlobalKey? scaffoldKey; @override Widget build(BuildContext context) { @@ -36,31 +36,31 @@ class DetailsView extends StatelessWidget { ? _details.title : Row( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( - icon: Icon(Icons.arrow_upward), + icon: const Icon(Icons.arrow_upward), onPressed: isFirst ? null : previous, ), IconButton( - icon: Icon(Icons.arrow_downward), + icon: const Icon(Icons.arrow_downward), onPressed: isLast ? null : next, ), ], ), - if (_details?.title != null) + if (_details.title != null) Expanded( child: Center(child: _details.title), ), ], ), - actions: _details?.actions, + actions: _details.actions, ), body: _details.child, - bottomNavigationBar: _details?.bottomAppBar, + bottomNavigationBar: _details.bottomAppBar, ); } } diff --git a/lib/templates/3-column/common/section_list.dart b/lib/templates/3-column/common/section_list.dart index f90026e..b963f9c 100644 --- a/lib/templates/3-column/common/section_list.dart +++ b/lib/templates/3-column/common/section_list.dart @@ -5,16 +5,16 @@ import '../three_column_navigation.dart'; class SectionList extends StatelessWidget { const SectionList({ - Key key, - @required this.controller, - @required MainSection section, - @required int listIndex, - @required this.listTap, - }) : _section = section, + Key? key, + required this.controller, + required MainSection section, + required int listIndex, + required this.listTap, + }) : _section = section, _listIndex = listIndex, super(key: key); - final AutoScrollController controller; + final AutoScrollController? controller; final MainSection _section; final int _listIndex; final ValueChanged listTap; @@ -26,12 +26,12 @@ class SectionList extends StatelessWidget { itemBuilder: (context, index) { final _item = _section.itemBuilder(context, index, _listIndex == index); return AutoScrollTag( - controller: controller, + controller: controller!, key: ValueKey(index), index: index, child: GestureDetector( - child: _item, onTap: () => listTap(index), + child: _item, ), ); }, diff --git a/lib/templates/3-column/common/sections.dart b/lib/templates/3-column/common/sections.dart index 55b2920..73bfbab 100644 --- a/lib/templates/3-column/common/sections.dart +++ b/lib/templates/3-column/common/sections.dart @@ -4,11 +4,11 @@ import '../three_column_navigation.dart'; class SectionsList extends StatelessWidget { const SectionsList({ - Key key, - @required this.sectionTap, - @required int sectionIndex, - @required this.sections, - }) : _sectionIndex = sectionIndex, + Key? key, + required this.sectionTap, + required int sectionIndex, + required this.sections, + }) : _sectionIndex = sectionIndex, super(key: key); final int _sectionIndex; diff --git a/lib/templates/3-column/three_column_navigation.dart b/lib/templates/3-column/three_column_navigation.dart index 37f702a..b0ca728 100644 --- a/lib/templates/3-column/three_column_navigation.dart +++ b/lib/templates/3-column/three_column_navigation.dart @@ -1,3 +1,4 @@ +import 'dart:developer' as developer show log; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -7,7 +8,8 @@ import 'common/index.dart'; class ThreeColumnNavigation extends StatefulWidget { ThreeColumnNavigation({ - @required this.sections, + Key? key, + required this.sections, this.showDetailsArrows = true, this.expandedIconData = Icons.fullscreen_exit, this.collapsedIconData = Icons.fullscreen, @@ -15,22 +17,22 @@ class ThreeColumnNavigation extends StatefulWidget { this.bottomAppBar, this.backgroundColor, this.title, - }); + }) : super(key: key); - final Color backgroundColor; - final Widget bottomAppBar; + final Color? backgroundColor; + final Widget? bottomAppBar; final IconData expandedIconData, collapsedIconData; final bool initiallyExpanded; List sections; final bool showDetailsArrows; - final Text title; + final Text? title; @override _ThreeColumnNavigationState createState() => _ThreeColumnNavigationState(); } class _ThreeColumnNavigationState extends State { - AutoScrollController controller; + AutoScrollController? controller; bool _expanded = true; int _listIndex = 0; @@ -39,10 +41,13 @@ class _ThreeColumnNavigationState extends State { @override void initState() { - if (!widget.initiallyExpanded) if (mounted) - setState(() { - _expanded = false; - }); + if (!widget.initiallyExpanded) { + if (mounted) { + setState(() { + _expanded = false; + }); + } + } _setUpController(true); super.initState(); @@ -59,13 +64,17 @@ class _ThreeColumnNavigationState extends State { Future _scrollToIndex(int value, {AutoScrollPosition position = AutoScrollPosition.middle}) async { try { - controller.scrollToIndex( + controller!.scrollToIndex( value, preferPosition: position, ); // controller.highlight(value); } on Exception catch (e) { - print('Could not scroll to index: $value => $e'); + developer.log( + 'Could not scroll to index: $value', + name: 'responsive_scaffold', + error: e.toString(), + ); } } @@ -82,19 +91,20 @@ class _ThreeColumnNavigationState extends State { child: Row( children: [ if (_expanded) - Container( + SizedBox( width: 300, child: Scaffold( - backgroundColor: widget?.backgroundColor, + backgroundColor: widget.backgroundColor, appBar: AppBar( - title: widget?.title, + title: widget.title, leading: IconButton( icon: Icon(widget.expandedIconData), onPressed: () { - if (mounted) + if (mounted) { setState(() { _expanded = false; }); + } }, ), ), @@ -103,18 +113,19 @@ class _ThreeColumnNavigationState extends State { sectionIndex: _sectionIndex, sectionTap: (index) { if (_sectionIndex != index) { - if (mounted) + if (mounted) { setState(() { _sectionIndex = index; }); + } _setUpController(false); } }, ), - bottomNavigationBar: widget?.bottomAppBar, + bottomNavigationBar: widget.bottomAppBar, ), ), - Container( + SizedBox( width: 400, child: Scaffold( drawerScrimColor: Colors.transparent, @@ -124,10 +135,11 @@ class _ThreeColumnNavigationState extends State { sectionIndex: _sectionIndex, sectionChanged: (context, index) { if (_sectionIndex != index) { - if (mounted) + if (mounted) { setState(() { _sectionIndex = index; }); + } _setUpController(false); Navigator.pop(context); } @@ -141,10 +153,11 @@ class _ThreeColumnNavigationState extends State { ? IconButton( icon: Icon(widget.collapsedIconData), onPressed: () { - if (mounted) + if (mounted) { setState(() { _expanded = true; }); + } }, ) : null, @@ -156,48 +169,49 @@ class _ThreeColumnNavigationState extends State { listIndex: _listIndex, listTap: (index) { if (_listIndex != index) { - if (mounted) + if (mounted) { setState(() { _listIndex = index; }); + } } }, ), bottomNavigationBar: - widget.sections[_sectionIndex]?.bottomAppBar, + widget.sections[_sectionIndex].bottomAppBar, ), ), Expanded( - child: Container( - child: Stack( - children: [ - DetailsView( - scaffoldKey: _scaffoldKey, - automaticallyImplyLeading: false, - isFirst: _listIndex == 0, - isLast: widget.sections[_sectionIndex].itemCount == - _listIndex + 1, - listIndex: _listIndex, - details: widget.sections[_sectionIndex] - .getDetails(context, _listIndex), - showDetailsArrows: widget.showDetailsArrows, - previous: () { - if (mounted) - setState(() { - _listIndex--; - }); - _scrollToIndex(_listIndex); - }, - next: () { - if (mounted) - setState(() { - _listIndex++; - }); - _scrollToIndex(_listIndex); - }, - ), - ], - ), + child: Stack( + children: [ + DetailsView( + scaffoldKey: _scaffoldKey, + automaticallyImplyLeading: false, + isFirst: _listIndex == 0, + isLast: widget.sections[_sectionIndex].itemCount == + _listIndex + 1, + listIndex: _listIndex, + details: widget.sections[_sectionIndex] + .getDetails(context, _listIndex), + showDetailsArrows: widget.showDetailsArrows, + previous: () { + if (mounted) { + setState(() { + _listIndex--; + }); + } + _scrollToIndex(_listIndex); + }, + next: () { + if (mounted) { + setState(() { + _listIndex++; + }); + } + _scrollToIndex(_listIndex); + }, + ), + ], ), ), ], @@ -210,10 +224,11 @@ class _ThreeColumnNavigationState extends State { sectionIndex: _sectionIndex, sectionChanged: (context, index) { if (_sectionIndex != index) { - if (mounted) + if (mounted) { setState(() { _sectionIndex = index; }); + } _setUpController(false); Navigator.pop(context); @@ -221,7 +236,7 @@ class _ThreeColumnNavigationState extends State { }, ), appBar: AppBar( - title: widget.sections[_sectionIndex]?.label, + title: widget.sections[_sectionIndex].label, ), body: SectionList( controller: controller, @@ -229,10 +244,11 @@ class _ThreeColumnNavigationState extends State { listIndex: _listIndex, listTap: (index) { if (_listIndex != index) { - if (mounted) + if (mounted) { setState(() { _listIndex = index; }); + } Navigator.of(context).push(MaterialPageRoute( builder: (_) { final _details = widget.sections[_sectionIndex] @@ -243,14 +259,14 @@ class _ThreeColumnNavigationState extends State { _listIndex == widget.sections.length - 1, listIndex: _listIndex, details: _details, - showDetailsArrows: false, + // showDetailsArrows: false, ); }, )); } }, ), - bottomNavigationBar: widget.sections[_sectionIndex]?.bottomAppBar, + bottomNavigationBar: widget.sections[_sectionIndex].bottomAppBar, ); }, ); @@ -259,9 +275,9 @@ class _ThreeColumnNavigationState extends State { class MenuButton extends StatelessWidget { const MenuButton({ - Key key, - @required GlobalKey scaffoldKey, - }) : _scaffoldKey = scaffoldKey, + Key? key, + required GlobalKey scaffoldKey, + }) : _scaffoldKey = scaffoldKey, super(key: key); final GlobalKey _scaffoldKey; @@ -269,7 +285,7 @@ class MenuButton extends StatelessWidget { @override Widget build(BuildContext context) { return IconButton( - icon: Icon(Icons.menu), + icon: const Icon(Icons.menu), onPressed: () { Scaffold.of(context).openDrawer(); // _scaffoldKey.currentState.showBodyScrim(true, 0.5); @@ -280,11 +296,11 @@ class MenuButton extends StatelessWidget { class SectionsDrawer extends StatelessWidget { const SectionsDrawer({ - Key key, - @required int sectionIndex, - @required this.sectionChanged, - @required this.sections, - }) : _sectionIndex = sectionIndex, + Key? key, + required int sectionIndex, + required this.sectionChanged, + required this.sections, + }) : _sectionIndex = sectionIndex, super(key: key); final List sections; @@ -307,15 +323,15 @@ class SectionsDrawer extends StatelessWidget { class MainSection { const MainSection({ - @required this.itemBuilder, - @required this.itemCount, - @required this.getDetails, - @required this.icon, - @required this.label, + required this.itemBuilder, + required this.itemCount, + required this.getDetails, + required this.icon, + required this.label, this.bottomAppBar, }); - final Widget bottomAppBar; + final Widget? bottomAppBar; final Icon icon; final int itemCount; final Text label; @@ -328,14 +344,14 @@ class MainSection { class DetailsWidget { const DetailsWidget({ - @required this.child, + required this.child, this.actions, this.title, this.bottomAppBar, }); - final List actions; - final Widget bottomAppBar; + final List? actions; + final Widget? bottomAppBar; final Widget child; - final Text title; + final Text? title; } diff --git a/lib/templates/layout/scaffold.dart b/lib/templates/layout/scaffold.dart index 343c849..49129f2 100644 --- a/lib/templates/layout/scaffold.dart +++ b/lib/templates/layout/scaffold.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; class ResponsiveScaffold extends StatelessWidget { const ResponsiveScaffold({ + Key? key, this.scaffoldKey, this.drawer, this.endDrawer, @@ -14,27 +15,27 @@ class ResponsiveScaffold extends StatelessWidget { this.kTabletBreakpoint = 720.0, this.kDesktopBreakpoint = 1440.0, this.appBarElevation, - }); + }) : super(key: key); - final Widget drawer, endDrawer; + final Widget? drawer, endDrawer; - final Widget title; + final Widget? title; - final Widget body; + final Widget? body; - final Widget trailing; + final Widget? trailing; - final Widget floatingActionButton; + final Widget? floatingActionButton; - final kTabletBreakpoint; - final kDesktopBreakpoint; - final _drawerWidth = 304.0; + final double kTabletBreakpoint; + final double kDesktopBreakpoint; + double get _drawerWidth => 304.0; - final IconData menuIcon, endIcon; + final IconData? menuIcon, endIcon; - final double appBarElevation; + final double? appBarElevation; - final Key scaffoldKey; + final Key? scaffoldKey; @override Widget build(BuildContext context) { @@ -51,7 +52,7 @@ class ResponsiveScaffold extends StatelessWidget { width: _drawerWidth, child: Drawer( child: SafeArea( - child: drawer, + child: drawer!, ), ), ), @@ -65,7 +66,7 @@ class ResponsiveScaffold extends StatelessWidget { title: title, actions: [ if (trailing != null) ...[ - trailing, + trailing!, ], ], ), @@ -75,12 +76,12 @@ class ResponsiveScaffold extends StatelessWidget { child: body ?? Container(), ), if (endDrawer != null) ...[ - Container( + SizedBox( width: _drawerWidth, child: Drawer( elevation: 3.0, child: SafeArea( - child: endDrawer, + child: endDrawer!, ), ), ), @@ -95,7 +96,7 @@ class ResponsiveScaffold extends StatelessWidget { Positioned( top: 100.0, left: _drawerWidth - 30, - child: floatingActionButton, + child: floatingActionButton!, ) ], ], @@ -109,7 +110,7 @@ class ResponsiveScaffold extends StatelessWidget { ? null : Drawer( child: SafeArea( - child: drawer, + child: drawer!, ), ), appBar: AppBar( @@ -119,7 +120,7 @@ class ResponsiveScaffold extends StatelessWidget { leading: _MenuButton(iconData: menuIcon), actions: [ if (trailing != null) ...[ - trailing, + trailing!, ], ], ), @@ -134,12 +135,12 @@ class ResponsiveScaffold extends StatelessWidget { child: body ?? Container(), ), if (endDrawer != null) ...[ - Container( + SizedBox( width: _drawerWidth, child: Drawer( elevation: 3.0, child: SafeArea( - child: endDrawer, + child: endDrawer!, ), ), ), @@ -150,7 +151,7 @@ class ResponsiveScaffold extends StatelessWidget { Positioned( top: 10.0, left: 10.0, - child: floatingActionButton, + child: floatingActionButton!, ) ], ], @@ -164,14 +165,14 @@ class ResponsiveScaffold extends StatelessWidget { ? null : Drawer( child: SafeArea( - child: drawer, + child: drawer!, ), ), endDrawer: endDrawer == null ? null : Drawer( child: SafeArea( - child: endDrawer, + child: endDrawer!, ), ), appBar: AppBar( @@ -181,7 +182,7 @@ class ResponsiveScaffold extends StatelessWidget { title: title, actions: [ if (trailing != null) ...[ - trailing, + trailing!, ], if (endDrawer != null) ...[ _OptionsButton(iconData: endIcon), @@ -199,11 +200,11 @@ class ResponsiveScaffold extends StatelessWidget { class _OptionsButton extends StatelessWidget { const _OptionsButton({ - Key key, - @required this.iconData, + Key? key, + required this.iconData, }) : super(key: key); - final IconData iconData; + final IconData? iconData; @override Widget build(BuildContext context) { @@ -218,11 +219,11 @@ class _OptionsButton extends StatelessWidget { class _MenuButton extends StatelessWidget { const _MenuButton({ - Key key, - @required this.iconData, + Key? key, + required this.iconData, }) : super(key: key); - final IconData iconData; + final IconData? iconData; @override Widget build(BuildContext context) { diff --git a/lib/templates/list/responsive_list.dart b/lib/templates/list/responsive_list.dart index 3019a37..d1594ae 100644 --- a/lib/templates/list/responsive_list.dart +++ b/lib/templates/list/responsive_list.dart @@ -8,13 +8,14 @@ export 'package:responsive_scaffold/data/classes/details.dart'; class ResponsiveListScaffold extends StatelessWidget { ResponsiveListScaffold({ + Key? key, this.tabletBreakpoint = 720.0, - @required this.detailBuilder, + required this.detailBuilder, this.appBar, this.drawer, this.slivers, this.endDrawer, - @required List children, + required List children, this.primary = true, // this.extendBody = false, this.drawerDragStartBehavior = DragStartBehavior.start, @@ -37,22 +38,24 @@ class ResponsiveListScaffold extends StatelessWidget { this.detailScaffoldKey, this.mobileRootNavigator = false, this.mobileNavigator, - }) : childDelagate = SliverChildListDelegate( + }) : childDelagate = SliverChildListDelegate( children, addAutomaticKeepAlives: false, addRepaintBoundaries: false, addSemanticIndexes: false, - ); + ), + super(key: key); ResponsiveListScaffold.builder({ + Key? key, this.tabletBreakpoint = 720.0, - @required this.detailBuilder, + required this.detailBuilder, this.appBar, this.drawer, this.slivers, this.endDrawer, - @required int itemCount, - @required IndexedWidgetBuilder itemBuilder, + required int itemCount, + required IndexedWidgetBuilder itemBuilder, this.primary = true, // this.extendBody = false, this.drawerDragStartBehavior = DragStartBehavior.start, @@ -75,22 +78,24 @@ class ResponsiveListScaffold extends StatelessWidget { this.detailScaffoldKey, this.mobileRootNavigator = false, this.mobileNavigator, - }) : childDelagate = SliverChildBuilderDelegate( + }) : childDelagate = SliverChildBuilderDelegate( itemBuilder, childCount: itemCount, addAutomaticKeepAlives: false, addRepaintBoundaries: false, addSemanticIndexes: false, - ); + ), + super(key: key); - ResponsiveListScaffold.custom({ + const ResponsiveListScaffold.custom({ + Key? key, this.tabletBreakpoint = 720.0, - @required this.detailBuilder, + required this.detailBuilder, this.appBar, this.drawer, this.slivers, this.endDrawer, - @required this.childDelagate, + required this.childDelagate, this.primary = true, // this.extendBody = false, this.drawerDragStartBehavior = DragStartBehavior.start, @@ -113,33 +118,33 @@ class ResponsiveListScaffold extends StatelessWidget { this.detailScaffoldKey, this.mobileRootNavigator = false, this.mobileNavigator, - }); + }) : super(key: key); final double tabletBreakpoint; final DetailWidgetBuilder detailBuilder; - final PreferredSizeWidget appBar; + final PreferredSizeWidget? appBar; - final Widget drawer, endDrawer; + final Widget? drawer, endDrawer; - final List slivers; + final List? slivers; - final Widget floatingActionButton; + final Widget? floatingActionButton; - final FloatingActionButtonLocation floatingActionButtonLocation; + final FloatingActionButtonLocation? floatingActionButtonLocation; - final Widget bottomNavigationBar; + final Widget? bottomNavigationBar; - final Widget bottomSheet; + final Widget? bottomSheet; - final List persistentFooterButtons; + final List? persistentFooterButtons; - final FloatingActionButtonAnimator floatingActionButtonAnimator; + final FloatingActionButtonAnimator? floatingActionButtonAnimator; - final bool resizeToAvoidBottomPadding; + final bool? resizeToAvoidBottomPadding; - final bool resizeToAvoidBottomInset; + final bool? resizeToAvoidBottomInset; final bool primary; @@ -147,13 +152,13 @@ class ResponsiveListScaffold extends StatelessWidget { final DragStartBehavior drawerDragStartBehavior; - final Color backgroundColor; + final Color? backgroundColor; - final Key scaffoldKey, detailScaffoldKey; + final Key? scaffoldKey, detailScaffoldKey; - final Widget tabletItemNotSelected; + final Widget? tabletItemNotSelected; - final Flexible tabletSideMenu; + final Flexible? tabletSideMenu; final int tabletFlexListView; @@ -161,9 +166,9 @@ class ResponsiveListScaffold extends StatelessWidget { final bool mobileRootNavigator; - final NavigatorState mobileNavigator; + final NavigatorState? mobileNavigator; - final Widget nullItems, emptyItems; + final Widget? nullItems, emptyItems; final SliverChildDelegate childDelagate; @@ -214,7 +219,7 @@ class ResponsiveListScaffold extends StatelessWidget { persistentFooterButtons: persistentFooterButtons, floatingActionButtonAnimator: floatingActionButtonAnimator, resizeToAvoidBottomInset: resizeToAvoidBottomInset, - resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, + // resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, primary: primary, // extendBody: extendBody, backgroundColor: backgroundColor, @@ -238,4 +243,4 @@ class ResponsiveListScaffold extends StatelessWidget { } typedef DetailWidgetBuilder = DetailsScreen Function( - BuildContext context, int index, bool tablet); + BuildContext context, int? index, bool tablet); diff --git a/lib/templates/list/views/mobile.dart b/lib/templates/list/views/mobile.dart index f6c74fd..63e93c8 100644 --- a/lib/templates/list/views/mobile.dart +++ b/lib/templates/list/views/mobile.dart @@ -5,16 +5,16 @@ import '../responsive_list.dart'; class MobileView extends StatelessWidget { MobileView({ - Key key, - @required this.slivers, - @required this.detailBuilder, - @required List children, - @required this.detailScaffoldKey, - @required this.useRootNavigator, - @required this.navigator, - @required this.nullItems, - @required this.emptyItems, - }) : childDelagate = SliverChildListDelegate( + Key? key, + required this.slivers, + required this.detailBuilder, + required List children, + required this.detailScaffoldKey, + required this.useRootNavigator, + required this.navigator, + required this.nullItems, + required this.emptyItems, + }) : childDelagate = SliverChildListDelegate( children, addAutomaticKeepAlives: false, addRepaintBoundaries: false, @@ -23,17 +23,17 @@ class MobileView extends StatelessWidget { super(key: key); MobileView.builder({ - Key key, - @required this.slivers, - @required this.detailBuilder, - @required int itemCount, - @required IndexedWidgetBuilder itemBuilder, - @required this.detailScaffoldKey, - @required this.useRootNavigator, - @required this.navigator, - @required this.nullItems, - @required this.emptyItems, - }) : childDelagate = SliverChildBuilderDelegate( + Key? key, + required this.slivers, + required this.detailBuilder, + required int itemCount, + required IndexedWidgetBuilder itemBuilder, + required this.detailScaffoldKey, + required this.useRootNavigator, + required this.navigator, + required this.nullItems, + required this.emptyItems, + }) : childDelagate = SliverChildBuilderDelegate( itemBuilder, childCount: itemCount, addAutomaticKeepAlives: false, @@ -42,58 +42,61 @@ class MobileView extends StatelessWidget { ), super(key: key); - MobileView.custom({ - Key key, - @required this.slivers, - @required this.detailBuilder, - @required this.childDelagate, - @required this.detailScaffoldKey, - @required this.useRootNavigator, - @required this.navigator, - @required this.nullItems, - @required this.emptyItems, + const MobileView.custom({ + Key? key, + required this.slivers, + required this.detailBuilder, + required this.childDelagate, + required this.detailScaffoldKey, + required this.useRootNavigator, + required this.navigator, + required this.nullItems, + required this.emptyItems, }) : super(key: key); - final List slivers; + final List? slivers; final DetailWidgetBuilder detailBuilder; - final Key detailScaffoldKey; + final Key? detailScaffoldKey; final bool useRootNavigator; - final NavigatorState navigator; - final Widget nullItems, emptyItems; + final NavigatorState? navigator; + final Widget? nullItems, emptyItems; final SliverChildDelegate childDelagate; @override Widget build(BuildContext context) { return CustomScrollView( - slivers: [] - ..addAll(slivers ?? []) - ..add(Builder( + slivers: [ + ...?slivers, + Builder( builder: (BuildContext context) { - if (childDelagate?.estimatedChildCount == null && nullItems != null) + if (childDelagate.estimatedChildCount == null && + nullItems != null) { return SliverFillRemaining(child: nullItems); - if (childDelagate?.estimatedChildCount != null && + } + if (childDelagate.estimatedChildCount != null && childDelagate.estimatedChildCount == 0 && - emptyItems != null) + emptyItems != null) { return SliverFillRemaining(child: emptyItems); + } return SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { - return new KeepAlive( + return KeepAlive( keepAlive: true, - child: new IndexedSemantics( + child: IndexedSemantics( index: index, child: GestureDetector( onTap: () { (navigator ?? Navigator.of(context)) .push(MaterialPageRoute(builder: (context) { final _details = detailBuilder(context, index, false); - return new DetailView( + return DetailView( detailScaffoldKey: detailScaffoldKey, itemCount: childDelagate.estimatedChildCount, details: _details); })); }, - child: new Container( + child: Container( padding: const EdgeInsets.symmetric(vertical: 8.0), child: childDelagate.build(context, index), ), @@ -101,35 +104,36 @@ class MobileView extends StatelessWidget { ), ); }, - childCount: childDelagate?.estimatedChildCount ?? 0, + childCount: childDelagate.estimatedChildCount ?? 0, addAutomaticKeepAlives: false, addRepaintBoundaries: false, addSemanticIndexes: false, )); }, - )), + ) + ], ); } } class DetailView extends StatelessWidget { const DetailView({ - Key key, - @required this.itemCount, - @required DetailsScreen details, - @required this.detailScaffoldKey, - }) : _details = details, + Key? key, + required this.itemCount, + required DetailsScreen details, + required this.detailScaffoldKey, + }) : _details = details, super(key: key); - final int itemCount; + final int? itemCount; final DetailsScreen _details; - final Key detailScaffoldKey; + final Key? detailScaffoldKey; @override Widget build(BuildContext context) { return Scaffold( key: detailScaffoldKey, - appBar: _details?.appBar, + appBar: _details.appBar, body: _details.body, ); } diff --git a/lib/templates/list/views/tablet.dart b/lib/templates/list/views/tablet.dart index 79aae04..1e76881 100644 --- a/lib/templates/list/views/tablet.dart +++ b/lib/templates/list/views/tablet.dart @@ -6,33 +6,33 @@ import '../responsive_list.dart'; class TabletView extends StatefulWidget { TabletView({ - Key key, - @required this.slivers, - @required this.detailBuilder, - @required List children, - @required this.itemNotSelected, - @required this.sideMenu, + Key? key, + required this.slivers, + required this.detailBuilder, + required List children, + required this.itemNotSelected, + required this.sideMenu, this.flexListView = 4, this.flexDetailView = 8, - @required this.appBar, - @required this.backgroundColor, - @required this.bottomNavigationBar, - @required this.bottomSheet, - @required this.drawer, - @required this.drawerDragStartBehavior, - @required this.endDrawer, - @required this.floatingActionButton, - @required this.floatingActionButtonAnimator, - @required this.floatingActionButtonLocation, - @required this.persistentFooterButtons, - @required this.primary, - @required this.resizeToAvoidBottomInset, - @required this.resizeToAvoidBottomPadding, - @required this.scaffoldkey, - @required this.detailScaffoldKey, - @required this.nullItems, - @required this.emptyItems, - }) : childDelagate = SliverChildListDelegate( + required this.appBar, + required this.backgroundColor, + required this.bottomNavigationBar, + required this.bottomSheet, + required this.drawer, + required this.drawerDragStartBehavior, + required this.endDrawer, + required this.floatingActionButton, + required this.floatingActionButtonAnimator, + required this.floatingActionButtonLocation, + required this.persistentFooterButtons, + required this.primary, + required this.resizeToAvoidBottomInset, + required this.resizeToAvoidBottomPadding, + required this.scaffoldkey, + required this.detailScaffoldKey, + required this.nullItems, + required this.emptyItems, + }) : childDelagate = SliverChildListDelegate( children, addAutomaticKeepAlives: false, addRepaintBoundaries: false, @@ -41,34 +41,34 @@ class TabletView extends StatefulWidget { super(key: key); TabletView.builder({ - Key key, - @required this.slivers, - @required this.detailBuilder, - @required int itemCount, - @required IndexedWidgetBuilder itemBuilder, - @required this.itemNotSelected, - @required this.sideMenu, + Key? key, + required this.slivers, + required this.detailBuilder, + required int itemCount, + required IndexedWidgetBuilder itemBuilder, + required this.itemNotSelected, + required this.sideMenu, this.flexListView = 4, this.flexDetailView = 8, - @required this.appBar, - @required this.backgroundColor, - @required this.bottomNavigationBar, - @required this.bottomSheet, - @required this.drawer, - @required this.drawerDragStartBehavior, - @required this.endDrawer, - @required this.floatingActionButton, - @required this.floatingActionButtonAnimator, - @required this.floatingActionButtonLocation, - @required this.persistentFooterButtons, - @required this.primary, - @required this.resizeToAvoidBottomInset, - @required this.resizeToAvoidBottomPadding, - @required this.scaffoldkey, - @required this.detailScaffoldKey, - @required this.nullItems, - @required this.emptyItems, - }) : childDelagate = SliverChildBuilderDelegate( + required this.appBar, + required this.backgroundColor, + required this.bottomNavigationBar, + required this.bottomSheet, + required this.drawer, + required this.drawerDragStartBehavior, + required this.endDrawer, + required this.floatingActionButton, + required this.floatingActionButtonAnimator, + required this.floatingActionButtonLocation, + required this.persistentFooterButtons, + required this.primary, + required this.resizeToAvoidBottomInset, + required this.resizeToAvoidBottomPadding, + required this.scaffoldkey, + required this.detailScaffoldKey, + required this.nullItems, + required this.emptyItems, + }) : childDelagate = SliverChildBuilderDelegate( itemBuilder, childCount: itemCount, addAutomaticKeepAlives: false, @@ -77,72 +77,72 @@ class TabletView extends StatefulWidget { ), super(key: key); - TabletView.custom({ - Key key, - @required this.slivers, - @required this.detailBuilder, - @required this.childDelagate, - @required this.itemNotSelected, - @required this.sideMenu, + const TabletView.custom({ + Key? key, + required this.slivers, + required this.detailBuilder, + required this.childDelagate, + required this.itemNotSelected, + required this.sideMenu, this.flexListView = 4, this.flexDetailView = 8, - @required this.appBar, - @required this.backgroundColor, - @required this.bottomNavigationBar, - @required this.bottomSheet, - @required this.drawer, - @required this.drawerDragStartBehavior, - @required this.endDrawer, - @required this.floatingActionButton, - @required this.floatingActionButtonAnimator, - @required this.floatingActionButtonLocation, - @required this.persistentFooterButtons, - @required this.primary, - @required this.resizeToAvoidBottomInset, - @required this.resizeToAvoidBottomPadding, - @required this.scaffoldkey, - @required this.detailScaffoldKey, - @required this.nullItems, - @required this.emptyItems, + required this.appBar, + required this.backgroundColor, + required this.bottomNavigationBar, + required this.bottomSheet, + required this.drawer, + required this.drawerDragStartBehavior, + required this.endDrawer, + required this.floatingActionButton, + required this.floatingActionButtonAnimator, + required this.floatingActionButtonLocation, + required this.persistentFooterButtons, + required this.primary, + required this.resizeToAvoidBottomInset, + required this.resizeToAvoidBottomPadding, + required this.scaffoldkey, + required this.detailScaffoldKey, + required this.nullItems, + required this.emptyItems, }) : super(key: key); - final List slivers; + final List? slivers; final DetailWidgetBuilder detailBuilder; - final Widget itemNotSelected; - final Flexible sideMenu; + final Widget? itemNotSelected; + final Flexible? sideMenu; final int flexListView; final int flexDetailView; - final Widget nullItems, emptyItems; + final Widget? nullItems, emptyItems; - final Widget floatingActionButton; + final Widget? floatingActionButton; - final FloatingActionButtonLocation floatingActionButtonLocation; + final FloatingActionButtonLocation? floatingActionButtonLocation; - final Widget bottomNavigationBar; + final Widget? bottomNavigationBar; - final Widget bottomSheet; + final Widget? bottomSheet; - final List persistentFooterButtons; + final List? persistentFooterButtons; - final FloatingActionButtonAnimator floatingActionButtonAnimator; + final FloatingActionButtonAnimator? floatingActionButtonAnimator; - final bool resizeToAvoidBottomPadding; + final bool? resizeToAvoidBottomPadding; - final bool resizeToAvoidBottomInset; + final bool? resizeToAvoidBottomInset; final bool primary; - final Key scaffoldkey, detailScaffoldKey; + final Key? scaffoldkey, detailScaffoldKey; // final bool extendBody; final DragStartBehavior drawerDragStartBehavior; - final Color backgroundColor; + final Color? backgroundColor; - final PreferredSizeWidget appBar; + final PreferredSizeWidget? appBar; - final Widget drawer, endDrawer; + final Widget? drawer, endDrawer; final SliverChildDelegate childDelagate; @@ -151,7 +151,7 @@ class TabletView extends StatefulWidget { } class _TabletViewState extends State { - int _index; + int? _index; void reset() { setState(() { @@ -171,47 +171,47 @@ class _TabletViewState extends State { body: Flex( direction: Axis.horizontal, children: [ - widget?.sideMenu ?? Container(), + widget.sideMenu ?? Container(), Flexible( flex: widget.flexListView, child: Scaffold( - key: widget?.scaffoldkey, - floatingActionButton: widget?.floatingActionButton, - floatingActionButtonLocation: - widget?.floatingActionButtonLocation, - bottomNavigationBar: widget?.bottomNavigationBar, - bottomSheet: widget?.bottomSheet, - persistentFooterButtons: widget?.persistentFooterButtons, - floatingActionButtonAnimator: - widget?.floatingActionButtonAnimator, - resizeToAvoidBottomInset: widget?.resizeToAvoidBottomInset, - resizeToAvoidBottomPadding: widget?.resizeToAvoidBottomPadding, - primary: widget?.primary, + key: widget.scaffoldkey, + floatingActionButton: widget.floatingActionButton, + floatingActionButtonLocation: widget.floatingActionButtonLocation, + bottomNavigationBar: widget.bottomNavigationBar, + bottomSheet: widget.bottomSheet, + persistentFooterButtons: widget.persistentFooterButtons, + floatingActionButtonAnimator: widget.floatingActionButtonAnimator, + resizeToAvoidBottomInset: widget.resizeToAvoidBottomInset, + // resizeToAvoidBottomPadding: widget.resizeToAvoidBottomPadding, + primary: widget.primary, // extendBody: extendBody, - backgroundColor: widget?.backgroundColor, - drawer: widget?.drawer, - endDrawer: widget?.endDrawer, - appBar: widget?.appBar, + backgroundColor: widget.backgroundColor, + drawer: widget.drawer, + endDrawer: widget.endDrawer, + appBar: widget.appBar, body: CustomScrollView( - slivers: [] - ..addAll(widget.slivers ?? []) - ..add(Builder( + slivers: [ + ...?widget.slivers, + Builder( builder: (BuildContext context) { - SliverChildDelegate _childDelagate = - widget?.childDelagate; - if (_childDelagate?.estimatedChildCount == null && - widget?.nullItems != null) + final SliverChildDelegate _childDelagate = + widget.childDelagate; + if (_childDelagate.estimatedChildCount == null && + widget.nullItems != null) { return SliverFillRemaining(child: widget.nullItems); - if (_childDelagate?.estimatedChildCount != null && + } + if (_childDelagate.estimatedChildCount != null && _childDelagate.estimatedChildCount == 0 && - widget?.emptyItems != null) + widget.emptyItems != null) { return SliverFillRemaining(child: widget.emptyItems); + } return SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { - return new KeepAlive( + return KeepAlive( keepAlive: true, - child: new IndexedSemantics( + child: IndexedSemantics( index: index, child: GestureDetector( onTap: () { @@ -219,12 +219,12 @@ class _TabletViewState extends State { _index = index; }); }, - child: new Container( + child: Container( color: _index == index ? Theme.of(context) .chipTheme .disabledColor - : widget?.backgroundColor, + : widget.backgroundColor, padding: const EdgeInsets.symmetric(vertical: 8.0), child: _childDelagate.build(context, index), @@ -233,25 +233,26 @@ class _TabletViewState extends State { ), ); }, - childCount: _childDelagate?.estimatedChildCount ?? 0, + childCount: _childDelagate.estimatedChildCount ?? 0, addAutomaticKeepAlives: false, addRepaintBoundaries: false, addSemanticIndexes: false, )); }, - )), + ) + ], ), ), ), Flexible( flex: widget.flexDetailView, - child: new _DetailView( - detailScaffoldKey: widget?.detailScaffoldKey, + child: _DetailView( + detailScaffoldKey: widget.detailScaffoldKey, details: _index == null || - _index > widget.childDelagate.estimatedChildCount - 1 + _index! > widget.childDelagate.estimatedChildCount! - 1 ? null : widget.detailBuilder(context, _index, true), - itemNotSelected: widget?.itemNotSelected, + itemNotSelected: widget.itemNotSelected, ), ), ], @@ -262,22 +263,22 @@ class _TabletViewState extends State { class _DetailView extends StatelessWidget { const _DetailView({ - Key key, - @required DetailsScreen details, - @required this.itemNotSelected, - @required this.detailScaffoldKey, - }) : _details = details, + Key? key, + required DetailsScreen? details, + required this.itemNotSelected, + required this.detailScaffoldKey, + }) : _details = details, super(key: key); - final DetailsScreen _details; - final Widget itemNotSelected; - final Key detailScaffoldKey; + final DetailsScreen? _details; + final Widget? itemNotSelected; + final Key? detailScaffoldKey; @override Widget build(BuildContext context) { if (_details == null) { return itemNotSelected ?? - Center( + const Center( child: Text("No Item Selected"), ); } diff --git a/pubspec.lock b/pubspec.lock index 848b629..68db061 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,62 +1,55 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.2" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" + version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" - collection: + version: "1.2.0" + clock: dependency: transitive description: - name: collection + name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" - convert: + version: "1.1.0" + collection: dependency: transitive description: - name: convert + name: collection url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - crypto: + version: "1.15.0" + fake_async: dependency: transitive description: - name: crypto + name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -67,62 +60,41 @@ packages: description: flutter source: sdk version: "0.0.0" - image: - dependency: transitive + lint: + dependency: "direct dev" description: - name: image + name: lint url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "1.5.3" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0+1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" + version: "1.8.0" scroll_to_index: dependency: "direct main" description: name: scroll_to_index url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "2.0.0" sky_engine: dependency: transitive description: flutter @@ -134,62 +106,55 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.5" + version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.11" + version: "0.2.19" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.5.0" + version: "2.1.0" sdks: - dart: ">=2.4.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 0dba2d7..366bf43 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,21 +2,22 @@ name: responsive_scaffold description: On mobile it shows a list and pushes to details and on tablet it shows the List and the selected item. version: 1.3.0+2 authors: - - Flutter Community - - Rody Davis + - Flutter Community + - Rody Davis homepage: https://github.com/fluttercommunity/responsive_scaffold maintainer: Rody Davis (@rodydavis) environment: - sdk: ">=2.2.2 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: sdk: flutter - scroll_to_index: ^1.0.5 + scroll_to_index: ^2.0.0 dev_dependencies: flutter_test: sdk: flutter + lint: any flutter: From 297c291b5875a11f980f4e1da5bee0674259b638 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Wed, 12 May 2021 21:45:35 +0200 Subject: [PATCH 2/5] add linting to example --- example/analysis_options.yaml | 1 + example/lib/examples/layout.dart | 22 ++++++++------ example/lib/examples/list.dart | 52 ++++++++++++++------------------ example/lib/examples/multi.dart | 32 +++++++++++--------- example/lib/main.dart | 13 +++++--- example/pubspec.lock | 9 +++++- example/pubspec.yaml | 2 ++ example/test/widget_test.dart | 2 +- pubspec.yaml | 2 +- 9 files changed, 73 insertions(+), 62 deletions(-) create mode 100644 example/analysis_options.yaml diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 0000000..2fcb805 --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lint/analysis_options_package.yaml diff --git a/example/lib/examples/layout.dart b/example/lib/examples/layout.dart index cc9e7c7..9adbf81 100644 --- a/example/lib/examples/layout.dart +++ b/example/lib/examples/layout.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:responsive_scaffold/responsive_scaffold.dart'; class LayoutExample extends StatelessWidget { + const LayoutExample({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ResponsiveScaffold( @@ -30,15 +32,15 @@ class LayoutExample extends StatelessWidget { endDrawer: ListView( children: [ ListTile( - leading: Icon(Icons.filter_list), - title: Text('Filter List'), - subtitle: Text('Hide and show items'), + leading: const Icon(Icons.filter_list), + title: const Text('Filter List'), + subtitle: const Text('Hide and show items'), trailing: Switch( value: true, onChanged: (val) {}, ), ), - ListTile( + const ListTile( leading: Icon(Icons.image_aspect_ratio), title: Text('Size Settings'), subtitle: Text('Change size of images'), @@ -50,9 +52,9 @@ class LayoutExample extends StatelessWidget { ), ), ListTile( - leading: Icon(Icons.sort_by_alpha), - title: Text('Sort List'), - subtitle: Text('Change layout behavior'), + leading: const Icon(Icons.sort_by_alpha), + title: const Text('Sort List'), + subtitle: const Text('Change layout behavior'), trailing: Switch( value: false, onChanged: (val) {}, @@ -61,21 +63,21 @@ class LayoutExample extends StatelessWidget { ], ), trailing: IconButton( - icon: Icon(Icons.search), + icon: const Icon(Icons.search), onPressed: () {}, ), body: Center( child: ElevatedButton( - child: Text('Close'), onPressed: () { Navigator.pop(context); }, + child: const Text('Close'), ), ), floatingActionButton: FloatingActionButton( - child: Icon(Icons.add), backgroundColor: Theme.of(context).accentColor, onPressed: () {}, + child: const Icon(Icons.add), ), ); } diff --git a/example/lib/examples/list.dart b/example/lib/examples/list.dart index 4842eff..3e6e050 100644 --- a/example/lib/examples/list.dart +++ b/example/lib/examples/list.dart @@ -2,16 +2,14 @@ import 'package:flutter/material.dart'; import 'package:responsive_scaffold/responsive_scaffold.dart'; class ListExample extends StatefulWidget { - const ListExample({ - Key? key, - }); + const ListExample({Key? key}) : super(key: key); @override _ListExampleState createState() => _ListExampleState(); } class _ListExampleState extends State { - var _scaffoldKey = GlobalKey(); + final _scaffoldKey = GlobalKey(); List? _items; @@ -46,9 +44,9 @@ class _ListExampleState extends State { ), ); }, - nullItems: Center(child: CircularProgressIndicator()), - emptyItems: Center(child: Text("No Items Found")), - slivers: [ + nullItems: const Center(child: CircularProgressIndicator()), + emptyItems: const Center(child: Text("No Items Found")), + slivers: const [ SliverAppBar( title: Text("App Bar"), ), @@ -62,20 +60,20 @@ class _ListExampleState extends State { }, bottomNavigationBar: BottomAppBar( elevation: 0.0, - child: Container( - child: IconButton( - icon: Icon(Icons.share), - onPressed: () {}, - ), + child: IconButton( + icon: const Icon(Icons.share), + onPressed: () {}, ), ), floatingActionButton: FloatingActionButton( - child: Icon(Icons.add), onPressed: () { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text("Snackbar!"), - )); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("Snackbar!"), + ), + ); }, + child: const Icon(Icons.add), ), ); } @@ -104,33 +102,29 @@ class ExampleDetailsScreen extends StatelessWidget { appBar: AppBar( elevation: 0.0, automaticallyImplyLeading: !tablet, - title: Text("Details"), + title: const Text("Details"), actions: [ IconButton( - icon: Icon(Icons.share), + icon: const Icon(Icons.share), onPressed: () { - onChanged(row + " " + DateTime.now().toString()); + onChanged("$row ${DateTime.now().toString()}"); }, ), IconButton( - icon: Icon(Icons.delete), + icon: const Icon(Icons.delete), onPressed: onDelete, ), ], ), bottomNavigationBar: BottomAppBar( elevation: 0.0, - child: Container( - child: IconButton( - icon: const Icon(Icons.share), - onPressed: () {}, - ), + child: IconButton( + icon: const Icon(Icons.share), + onPressed: () {}, ), ), - body: Container( - child: Center( - child: Text("Item: $row"), - ), + body: Center( + child: Text("Item: $row"), ), ); } diff --git a/example/lib/examples/multi.dart b/example/lib/examples/multi.dart index 47544a4..8ba5e9c 100644 --- a/example/lib/examples/multi.dart +++ b/example/lib/examples/multi.dart @@ -2,18 +2,20 @@ import 'package:flutter/material.dart'; import 'package:responsive_scaffold/responsive_scaffold.dart'; class MultiColumnNavigationExample extends StatelessWidget { + const MultiColumnNavigationExample({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ThreeColumnNavigation( - title: Text('Mailboxes'), - showDetailsArrows: true, + title: const Text('Mailboxes'), + // showDetailsArrows: true, backgroundColor: Colors.grey[100], bottomAppBar: BottomAppBar( elevation: 1, child: Row( children: [ IconButton( - icon: Icon( + icon: const Icon( Icons.filter_list, color: Colors.transparent, ), @@ -24,8 +26,8 @@ class MultiColumnNavigationExample extends StatelessWidget { ), sections: [ MainSection( - label: Text('All Inboxes'), - icon: Icon(Icons.mail), + label: const Text('All Inboxes'), + icon: const Icon(Icons.mail), itemCount: 100, itemBuilder: (BuildContext context, int index, bool selected) { return ListTile( @@ -33,8 +35,8 @@ class MultiColumnNavigationExample extends StatelessWidget { child: Text(index.toString()), ), selected: selected, - title: Text('Primary Information'), - subtitle: Text('Here are some details about the item'), + title: const Text('Primary Information'), + subtitle: const Text('Here are some details about the item'), ); }, bottomAppBar: BottomAppBar( @@ -42,7 +44,7 @@ class MultiColumnNavigationExample extends StatelessWidget { child: Row( children: [ IconButton( - icon: Icon(Icons.filter_list), + icon: const Icon(Icons.filter_list), onPressed: () {}, ), ], @@ -50,7 +52,7 @@ class MultiColumnNavigationExample extends StatelessWidget { ), getDetails: (context, index) { return DetailsWidget( - title: Text('Details'), + title: const Text('Details'), child: Center( child: Text( index.toString(), @@ -60,8 +62,8 @@ class MultiColumnNavigationExample extends StatelessWidget { }, ), MainSection( - label: Text('Sent Mail'), - icon: Icon(Icons.send), + label: const Text('Sent Mail'), + icon: const Icon(Icons.send), itemCount: 100, itemBuilder: (context, index, selected) { return ListTile( @@ -69,16 +71,16 @@ class MultiColumnNavigationExample extends StatelessWidget { child: Text(index.toString()), ), selected: selected, - title: Text('Secondary Information'), - subtitle: Text('Here are some details about the item'), + title: const Text('Secondary Information'), + subtitle: const Text('Here are some details about the item'), ); }, getDetails: (context, index) { return DetailsWidget( - title: Text('Details'), + title: const Text('Details'), actions: [ IconButton( - icon: Icon(Icons.share), + icon: const Icon(Icons.share), onPressed: () {}, ), ], diff --git a/example/lib/main.dart b/example/lib/main.dart index 40a82ea..7d27f21 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -9,7 +9,7 @@ import 'examples/index.dart'; void main() { // Desktop platforms aren't a valid platform. if (!kIsWeb) _setTargetPlatformForDesktop(); - return runApp(MyApp()); + return runApp(const MyApp()); } /// If the current platform is desktop, override the default platform to @@ -28,12 +28,14 @@ void _setTargetPlatformForDesktop() { } class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData.light().copyWith(accentColor: Colors.red), debugShowCheckedModeBanner: false, - home: HomePage(), + home: const HomePage(), ); } } @@ -53,15 +55,16 @@ class HomePage extends StatelessWidget { children: [ ListTile( title: const Text('Responsive List'), - onTap: () => _goToScreen(context, ListExample()), + onTap: () => _goToScreen(context, const ListExample()), ), ListTile( title: const Text('Responsive Layout'), - onTap: () => _goToScreen(context, LayoutExample()), + onTap: () => _goToScreen(context, const LayoutExample()), ), ListTile( title: const Text('Multi Column Layout'), - onTap: () => _goToScreen(context, MultiColumnNavigationExample()), + onTap: () => + _goToScreen(context, const MultiColumnNavigationExample()), ), ], ), diff --git a/example/pubspec.lock b/example/pubspec.lock index f29df12..11ef53c 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -49,7 +49,7 @@ packages: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "0.1.3" fake_async: dependency: transitive description: @@ -67,6 +67,13 @@ packages: description: flutter source: sdk version: "0.0.0" + lint: + dependency: "direct dev" + description: + name: lint + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.3" matcher: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index a67dba8..1634494 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -20,6 +20,8 @@ dev_dependencies: responsive_scaffold: path: ../ + lint: ^1.5.3 + # For information on the generic Dart part of this file, see the # following page: https://www.dartlang.org/tools/pub/pubspec diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 7418a4e..4febcbe 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:responsive_scaffold_example/main.dart'; void main() { testWidgets('Verify Platform version', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); + await tester.pumpWidget(const MyApp()); // Verify that platform version is retrieved. expect( diff --git a/pubspec.yaml b/pubspec.yaml index 366bf43..0f68c1d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,6 +18,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - lint: any + lint: ^1.5.3 flutter: From a2fc7594c4be0f835dcd277a3f5b93f9e854c0a6 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Thu, 13 May 2021 12:45:10 +0200 Subject: [PATCH 3/5] fix documentation --- README.md | 226 ++++++++++++++++-------------- example/README.md | 230 +++++++++++++++++-------------- example/lib/examples/list.dart | 16 +-- example/pubspec.yaml | 16 +-- lib/templates/3-column/README.md | 34 ++--- 5 files changed, 286 insertions(+), 236 deletions(-) diff --git a/README.md b/README.md index 080d160..b956d99 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,14 @@ import 'package:flutter/material.dart'; import 'package:responsive_scaffold/responsive_scaffold.dart'; class LayoutExample extends StatelessWidget { + const LayoutExample({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ResponsiveScaffold( - title: Text('Responsive Layout Example'), + title: const Text('Responsive Layout Example'), drawer: ListView( - children: [ + children: const [ ListTile( leading: Icon(Icons.settings), title: Text('Settings Page'), @@ -70,15 +72,15 @@ class LayoutExample extends StatelessWidget { endDrawer: ListView( children: [ ListTile( - leading: Icon(Icons.filter_list), - title: Text('Filter List'), - subtitle: Text('Hide and show items'), + leading: const Icon(Icons.filter_list), + title: const Text('Filter List'), + subtitle: const Text('Hide and show items'), trailing: Switch( value: true, onChanged: (val) {}, ), ), - ListTile( + const ListTile( leading: Icon(Icons.image_aspect_ratio), title: Text('Size Settings'), subtitle: Text('Change size of images'), @@ -90,9 +92,9 @@ class LayoutExample extends StatelessWidget { ), ), ListTile( - leading: Icon(Icons.sort_by_alpha), - title: Text('Sort List'), - subtitle: Text('Change layout behavior'), + leading: const Icon(Icons.sort_by_alpha), + title: const Text('Sort List'), + subtitle: const Text('Change layout behavior'), trailing: Switch( value: false, onChanged: (val) {}, @@ -101,27 +103,26 @@ class LayoutExample extends StatelessWidget { ], ), trailing: IconButton( - icon: Icon(Icons.search), + icon: const Icon(Icons.search), onPressed: () {}, ), body: Center( - child: RaisedButton( - child: Text('Close'), + child: ElevatedButton( onPressed: () { Navigator.pop(context); }, + child: const Text('Close'), ), ), floatingActionButton: FloatingActionButton( - child: Icon(Icons.add), backgroundColor: Theme.of(context).accentColor, onPressed: () {}, + child: const Icon(Icons.add), ), ); } } - ``` ### Responsive List @@ -141,107 +142,132 @@ class LayoutExample extends StatelessWidget { ``` dart import 'package:flutter/material.dart'; - import 'package:responsive_scaffold/responsive_scaffold.dart'; -void main() => runApp(MyApp()); +class ListExample extends StatefulWidget { + const ListExample({Key? key}) : super(key: key); -class MyApp extends StatefulWidget { @override - _MyAppState createState() => _MyAppState(); + _ListExampleState createState() => _ListExampleState(); } -class _MyAppState extends State { - var _scaffoldKey = new GlobalKey(); +class _ListExampleState extends State { + final _scaffoldKey = GlobalKey(); + + late List _items; + + @override + void initState() { + _items = List.generate(20, (int index) => "test_$index"); + super.initState(); + } @override Widget build(BuildContext context) { - return MaterialApp( - home: ResponsiveListScaffold.builder( - scaffoldKey: _scaffoldKey, - detailBuilder: (BuildContext context, int index, bool tablet) { - return DetailsScreen( - // appBar: AppBar( - // elevation: 0.0, - // title: Text("Details"), - // actions: [ - // IconButton( - // icon: Icon(Icons.share), - // onPressed: () {}, - // ), - // IconButton( - // icon: Icon(Icons.delete), - // onPressed: () { - // if (!tablet) Navigator.of(context).pop(); - // }, - // ), - // ], - // ), - body: Scaffold( - appBar: AppBar( - elevation: 0.0, - title: Text("Details"), - automaticallyImplyLeading: !tablet, - actions: [ - IconButton( - icon: Icon(Icons.share), - onPressed: () {}, - ), - IconButton( - icon: Icon(Icons.delete), - onPressed: () { - if (!tablet) Navigator.of(context).pop(); - }, - ), - ], - ), - bottomNavigationBar: BottomAppBar( - elevation: 0.0, - child: Container( - child: IconButton( - icon: Icon(Icons.share), - onPressed: () {}, - ), - ), - ), - body: Container( - child: Center( - child: Text("Item: $index"), - ), - ), + return ResponsiveListScaffold.builder( + scaffoldKey: _scaffoldKey, + detailBuilder: (BuildContext context, int? index, bool tablet) { + final i = _items[index!]; + return DetailsScreen( + body: ExampleDetailsScreen( + items: _items, + row: i, + tablet: tablet, + onDelete: () { + setState(() { + _items.removeAt(index); + }); + if (!tablet) Navigator.of(context).pop(); + }, + onChanged: (String value) { + setState(() { + _items[index] = value; + }); + }, + ), + ); + }, + nullItems: const Center(child: CircularProgressIndicator()), + emptyItems: const Center(child: Text("No Items Found")), + slivers: const [ + SliverAppBar( + title: Text("App Bar"), + ), + ], + itemCount: _items.length, + itemBuilder: (BuildContext context, int index) { + final i = _items[index]; + return ListTile( + leading: Text(i), + ); + }, + bottomNavigationBar: BottomAppBar( + elevation: 0.0, + child: IconButton( + icon: const Icon(Icons.share), + onPressed: () {}, + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("Snackbar!"), ), ); }, - nullItems: Center(child: CircularProgressIndicator()), - emptyItems: Center(child: Text("No Items Found")), - slivers: [ - SliverAppBar( - title: Text("App Bar"), + child: const Icon(Icons.add), + ), + ); + } +} + +class ExampleDetailsScreen extends StatelessWidget { + const ExampleDetailsScreen({ + Key? key, + required List items, + required this.row, + required this.tablet, + required this.onDelete, + required this.onChanged, + }) : _items = items, + super(key: key); + + final List _items; + final String row; + final bool tablet; + final VoidCallback onDelete; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0.0, + automaticallyImplyLeading: !tablet, + title: const Text("Details"), + actions: [ + IconButton( + icon: const Icon(Icons.share), + onPressed: () { + onChanged("$row ${DateTime.now().toString()}"); + }, ), - ], - itemCount: 100, - itemBuilder: (BuildContext context, int index) { - return ListTile( - leading: Text(index.toString()), - ); - }, - bottomNavigationBar: BottomAppBar( - elevation: 0.0, - child: Container( - child: IconButton( - icon: Icon(Icons.share), - onPressed: () {}, - ), + IconButton( + icon: const Icon(Icons.delete), + onPressed: onDelete, ), + ], + ), + bottomNavigationBar: BottomAppBar( + elevation: 0.0, + child: IconButton( + icon: const Icon(Icons.share), + onPressed: () {}, ), - floatingActionButton: FloatingActionButton( - child: Icon(Icons.add), - onPressed: () { - _scaffoldKey.currentState.showSnackBar(SnackBar( - content: Text("Snackbar!"), - )); - }, - ), + ), + body: Center( + child: Text("Item: $row"), ), ); } diff --git a/example/README.md b/example/README.md index 6bd0647..b8376bf 100644 --- a/example/README.md +++ b/example/README.md @@ -4,17 +4,19 @@ Demonstrates how to use the responsive_scaffold plugin. ## Responsive Layout Example -``` dart +``` dart import 'package:flutter/material.dart'; import 'package:responsive_scaffold/responsive_scaffold.dart'; class LayoutExample extends StatelessWidget { + const LayoutExample({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ResponsiveScaffold( - title: Text('Responsive Layout Example'), + title: const Text('Responsive Layout Example'), drawer: ListView( - children: [ + children: const [ ListTile( leading: Icon(Icons.settings), title: Text('Settings Page'), @@ -37,15 +39,15 @@ class LayoutExample extends StatelessWidget { endDrawer: ListView( children: [ ListTile( - leading: Icon(Icons.filter_list), - title: Text('Filter List'), - subtitle: Text('Hide and show items'), + leading: const Icon(Icons.filter_list), + title: const Text('Filter List'), + subtitle: const Text('Hide and show items'), trailing: Switch( value: true, onChanged: (val) {}, ), ), - ListTile( + const ListTile( leading: Icon(Icons.image_aspect_ratio), title: Text('Size Settings'), subtitle: Text('Change size of images'), @@ -57,9 +59,9 @@ class LayoutExample extends StatelessWidget { ), ), ListTile( - leading: Icon(Icons.sort_by_alpha), - title: Text('Sort List'), - subtitle: Text('Change layout behavior'), + leading: const Icon(Icons.sort_by_alpha), + title: const Text('Sort List'), + subtitle: const Text('Change layout behavior'), trailing: Switch( value: false, onChanged: (val) {}, @@ -68,21 +70,21 @@ class LayoutExample extends StatelessWidget { ], ), trailing: IconButton( - icon: Icon(Icons.search), + icon: const Icon(Icons.search), onPressed: () {}, ), body: Center( - child: RaisedButton( - child: Text('Close'), + child: ElevatedButton( onPressed: () { Navigator.pop(context); }, + child: const Text('Close'), ), ), floatingActionButton: FloatingActionButton( - child: Icon(Icons.add), backgroundColor: Theme.of(context).accentColor, onPressed: () {}, + child: const Icon(Icons.add), ), ); } @@ -92,113 +94,137 @@ class LayoutExample extends StatelessWidget { ## Responsive List Example -``` dart +``` dart import 'package:flutter/material.dart'; - import 'package:responsive_scaffold/responsive_scaffold.dart'; -void main() => runApp(MyApp()); +class ListExample extends StatefulWidget { + const ListExample({Key? key}) : super(key: key); -class MyApp extends StatefulWidget { @override - _MyAppState createState() => _MyAppState(); + _ListExampleState createState() => _ListExampleState(); } -class _MyAppState extends State { - var _scaffoldKey = new GlobalKey(); +class _ListExampleState extends State { + final _scaffoldKey = GlobalKey(); + + late List _items; + + @override + void initState() { + _items = List.generate(20, (int index) => "test_$index"); + super.initState(); + } @override Widget build(BuildContext context) { - return MaterialApp( - home: ResponsiveListScaffold.builder( - scaffoldKey: _scaffoldKey, - detailBuilder: (BuildContext context, int index, bool tablet) { - return DetailsScreen( - // appBar: AppBar( - // elevation: 0.0, - // title: Text("Details"), - // actions: [ - // IconButton( - // icon: Icon(Icons.share), - // onPressed: () {}, - // ), - // IconButton( - // icon: Icon(Icons.delete), - // onPressed: () { - // if (!tablet) Navigator.of(context).pop(); - // }, - // ), - // ], - // ), - body: Scaffold( - appBar: AppBar( - elevation: 0.0, - title: Text("Details"), - automaticallyImplyLeading: !tablet, - actions: [ - IconButton( - icon: Icon(Icons.share), - onPressed: () {}, - ), - IconButton( - icon: Icon(Icons.delete), - onPressed: () { - if (!tablet) Navigator.of(context).pop(); - }, - ), - ], - ), - bottomNavigationBar: BottomAppBar( - elevation: 0.0, - child: Container( - child: IconButton( - icon: Icon(Icons.share), - onPressed: () {}, - ), - ), - ), - body: Container( - child: Center( - child: Text("Item: $index"), - ), - ), + return ResponsiveListScaffold.builder( + scaffoldKey: _scaffoldKey, + detailBuilder: (BuildContext context, int? index, bool tablet) { + final i = _items[index!]; + return DetailsScreen( + body: ExampleDetailsScreen( + items: _items, + row: i, + tablet: tablet, + onDelete: () { + setState(() { + _items.removeAt(index); + }); + if (!tablet) Navigator.of(context).pop(); + }, + onChanged: (String value) { + setState(() { + _items[index] = value; + }); + }, + ), + ); + }, + nullItems: const Center(child: CircularProgressIndicator()), + emptyItems: const Center(child: Text("No Items Found")), + slivers: const [ + SliverAppBar( + title: Text("App Bar"), + ), + ], + itemCount: _items.length, + itemBuilder: (BuildContext context, int index) { + final i = _items[index]; + return ListTile( + leading: Text(i), + ); + }, + bottomNavigationBar: BottomAppBar( + elevation: 0.0, + child: IconButton( + icon: const Icon(Icons.share), + onPressed: () {}, + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("Snackbar!"), ), ); }, - nullItems: Center(child: CircularProgressIndicator()), - emptyItems: Center(child: Text("No Items Found")), - slivers: [ - SliverAppBar( - title: Text("App Bar"), + child: const Icon(Icons.add), + ), + ); + } +} + +class ExampleDetailsScreen extends StatelessWidget { + const ExampleDetailsScreen({ + Key? key, + required List items, + required this.row, + required this.tablet, + required this.onDelete, + required this.onChanged, + }) : _items = items, + super(key: key); + + final List _items; + final String row; + final bool tablet; + final VoidCallback onDelete; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0.0, + automaticallyImplyLeading: !tablet, + title: const Text("Details"), + actions: [ + IconButton( + icon: const Icon(Icons.share), + onPressed: () { + onChanged("$row ${DateTime.now().toString()}"); + }, ), - ], - itemCount: 100, - itemBuilder: (BuildContext context, int index) { - return ListTile( - leading: Text(index.toString()), - ); - }, - bottomNavigationBar: BottomAppBar( - elevation: 0.0, - child: Container( - child: IconButton( - icon: Icon(Icons.share), - onPressed: () {}, - ), + IconButton( + icon: const Icon(Icons.delete), + onPressed: onDelete, ), + ], + ), + bottomNavigationBar: BottomAppBar( + elevation: 0.0, + child: IconButton( + icon: const Icon(Icons.share), + onPressed: () {}, ), - floatingActionButton: FloatingActionButton( - child: Icon(Icons.add), - onPressed: () { - _scaffoldKey.currentState.showSnackBar(SnackBar( - content: Text("Snackbar!"), - )); - }, - ), + ), + body: Center( + child: Text("Item: $row"), ), ); } } - ``` \ No newline at end of file diff --git a/example/lib/examples/list.dart b/example/lib/examples/list.dart index 3e6e050..d7e5208 100644 --- a/example/lib/examples/list.dart +++ b/example/lib/examples/list.dart @@ -11,7 +11,7 @@ class ListExample extends StatefulWidget { class _ListExampleState extends State { final _scaffoldKey = GlobalKey(); - List? _items; + late List _items; @override void initState() { @@ -24,7 +24,7 @@ class _ListExampleState extends State { return ResponsiveListScaffold.builder( scaffoldKey: _scaffoldKey, detailBuilder: (BuildContext context, int? index, bool tablet) { - final i = _items![index!]; + final i = _items[index!]; return DetailsScreen( body: ExampleDetailsScreen( items: _items, @@ -32,13 +32,13 @@ class _ListExampleState extends State { tablet: tablet, onDelete: () { setState(() { - _items!.removeAt(index); + _items.removeAt(index); }); if (!tablet) Navigator.of(context).pop(); }, onChanged: (String value) { setState(() { - _items![index] = value; + _items[index] = value; }); }, ), @@ -51,9 +51,9 @@ class _ListExampleState extends State { title: Text("App Bar"), ), ], - itemCount: _items?.length ?? 0, + itemCount: _items.length, itemBuilder: (BuildContext context, int index) { - final i = _items![index]; + final i = _items[index]; return ListTile( leading: Text(i), ); @@ -82,7 +82,7 @@ class _ListExampleState extends State { class ExampleDetailsScreen extends StatelessWidget { const ExampleDetailsScreen({ Key? key, - required List? items, + required List items, required this.row, required this.tablet, required this.onDelete, @@ -90,7 +90,7 @@ class ExampleDetailsScreen extends StatelessWidget { }) : _items = items, super(key: key); - final List? _items; + final List _items; final String row; final bool tablet; final VoidCallback onDelete; diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 1634494..8dd8aaf 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,49 +1,45 @@ name: responsive_scaffold_example description: Demonstrates how to use the responsive_scaffold plugin. -publish_to: 'none' +publish_to: "none" environment: - sdk: '>=2.12.0 <3.0.0' + sdk: ">=2.12.0 <3.0.0" dependencies: + cupertino_icons: ^0.1.2 + flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.2 dev_dependencies: flutter_test: sdk: flutter + lint: ^1.5.3 + responsive_scaffold: path: ../ - lint: ^1.5.3 - # For information on the generic Dart part of this file, see the # following page: https://www.dartlang.org/tools/pub/pubspec # The following section is specific to Flutter. flutter: - # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true - # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg - # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.io/assets-and-images/#resolution-aware. - # For details regarding adding assets from package dependencies, see # https://flutter.io/assets-and-images/#from-packages - # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a # "family" key with the font family name, and a "fonts" key with a diff --git a/lib/templates/3-column/README.md b/lib/templates/3-column/README.md index cd8fa5c..9b0205c 100644 --- a/lib/templates/3-column/README.md +++ b/lib/templates/3-column/README.md @@ -16,18 +16,20 @@ import 'package:flutter/material.dart'; import 'package:responsive_scaffold/responsive_scaffold.dart'; class MultiColumnNavigationExample extends StatelessWidget { + const MultiColumnNavigationExample({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ThreeColumnNavigation( - title: Text('Mailboxes'), - showDetailsArrows: true, + title: const Text('Mailboxes'), + // showDetailsArrows: true, backgroundColor: Colors.grey[100], bottomAppBar: BottomAppBar( elevation: 1, child: Row( children: [ IconButton( - icon: Icon( + icon: const Icon( Icons.filter_list, color: Colors.transparent, ), @@ -38,17 +40,17 @@ class MultiColumnNavigationExample extends StatelessWidget { ), sections: [ MainSection( - label: Text('All Inboxes'), - icon: Icon(Icons.mail), + label: const Text('All Inboxes'), + icon: const Icon(Icons.mail), itemCount: 100, - itemBuilder: (context, index, selected) { + itemBuilder: (BuildContext context, int index, bool selected) { return ListTile( leading: CircleAvatar( child: Text(index.toString()), ), selected: selected, - title: Text('Primary Information'), - subtitle: Text('Here are some details about the item'), + title: const Text('Primary Information'), + subtitle: const Text('Here are some details about the item'), ); }, bottomAppBar: BottomAppBar( @@ -56,7 +58,7 @@ class MultiColumnNavigationExample extends StatelessWidget { child: Row( children: [ IconButton( - icon: Icon(Icons.filter_list), + icon: const Icon(Icons.filter_list), onPressed: () {}, ), ], @@ -64,7 +66,7 @@ class MultiColumnNavigationExample extends StatelessWidget { ), getDetails: (context, index) { return DetailsWidget( - title: Text('Details'), + title: const Text('Details'), child: Center( child: Text( index.toString(), @@ -74,8 +76,8 @@ class MultiColumnNavigationExample extends StatelessWidget { }, ), MainSection( - label: Text('Sent Mail'), - icon: Icon(Icons.send), + label: const Text('Sent Mail'), + icon: const Icon(Icons.send), itemCount: 100, itemBuilder: (context, index, selected) { return ListTile( @@ -83,16 +85,16 @@ class MultiColumnNavigationExample extends StatelessWidget { child: Text(index.toString()), ), selected: selected, - title: Text('Secondary Information'), - subtitle: Text('Here are some details about the item'), + title: const Text('Secondary Information'), + subtitle: const Text('Here are some details about the item'), ); }, getDetails: (context, index) { return DetailsWidget( - title: Text('Details'), + title: const Text('Details'), actions: [ IconButton( - icon: Icon(Icons.share), + icon: const Icon(Icons.share), onPressed: () {}, ), ], From a5276edc92ecdea70eef6c189178e702ce1dc2fd Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Thu, 13 May 2021 12:46:16 +0200 Subject: [PATCH 4/5] bump version 2.0.0 --- example/pubspec.lock | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 11ef53c..859a92e 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -101,7 +101,7 @@ packages: path: ".." relative: true source: path - version: "1.3.0+2" + version: "2.0.0+1" scroll_to_index: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0f68c1d..9d490fb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: responsive_scaffold description: On mobile it shows a list and pushes to details and on tablet it shows the List and the selected item. -version: 1.3.0+2 +version: 2.0.0+1 authors: - Flutter Community - Rody Davis From 240ccf080d7241ec6dcea4c37dad4526dd1d5da3 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Tue, 27 Jul 2021 16:32:42 +0200 Subject: [PATCH 5/5] fix nullability of detailscreen index --- README.md | 4 ++-- example/README.md | 4 ++-- example/lib/examples/list.dart | 9 +++------ example/pubspec.lock | 6 +++--- lib/templates/3-column/common/details.dart | 4 +--- lib/templates/3-column/three_column_navigation.dart | 8 +++----- lib/templates/list/responsive_list.dart | 2 +- lib/templates/list/views/tablet.dart | 2 +- 8 files changed, 16 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index b956d99..24c6efb 100644 --- a/README.md +++ b/README.md @@ -166,8 +166,8 @@ class _ListExampleState extends State { Widget build(BuildContext context) { return ResponsiveListScaffold.builder( scaffoldKey: _scaffoldKey, - detailBuilder: (BuildContext context, int? index, bool tablet) { - final i = _items[index!]; + detailBuilder: (BuildContext context, int index, bool tablet) { + final i = _items[index]; return DetailsScreen( body: ExampleDetailsScreen( items: _items, diff --git a/example/README.md b/example/README.md index b8376bf..8972705 100644 --- a/example/README.md +++ b/example/README.md @@ -120,8 +120,8 @@ class _ListExampleState extends State { Widget build(BuildContext context) { return ResponsiveListScaffold.builder( scaffoldKey: _scaffoldKey, - detailBuilder: (BuildContext context, int? index, bool tablet) { - final i = _items[index!]; + detailBuilder: (BuildContext context, int index, bool tablet) { + final i = _items[index]; return DetailsScreen( body: ExampleDetailsScreen( items: _items, diff --git a/example/lib/examples/list.dart b/example/lib/examples/list.dart index d7e5208..6b62fe3 100644 --- a/example/lib/examples/list.dart +++ b/example/lib/examples/list.dart @@ -23,11 +23,10 @@ class _ListExampleState extends State { Widget build(BuildContext context) { return ResponsiveListScaffold.builder( scaffoldKey: _scaffoldKey, - detailBuilder: (BuildContext context, int? index, bool tablet) { - final i = _items[index!]; + detailBuilder: (BuildContext context, int index, bool tablet) { + final i = _items[index]; return DetailsScreen( body: ExampleDetailsScreen( - items: _items, row: i, tablet: tablet, onDelete: () { @@ -82,15 +81,13 @@ class _ListExampleState extends State { class ExampleDetailsScreen extends StatelessWidget { const ExampleDetailsScreen({ Key? key, - required List items, required this.row, required this.tablet, required this.onDelete, required this.onChanged, - }) : _items = items, + }) : super(key: key); - final List _items; final String row; final bool tablet; final VoidCallback onDelete; diff --git a/example/pubspec.lock b/example/pubspec.lock index 859a92e..781fef5 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.6.1" boolean_selector: dependency: transitive description: @@ -120,7 +120,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -155,7 +155,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.3.0" typed_data: dependency: transitive description: diff --git a/lib/templates/3-column/common/details.dart b/lib/templates/3-column/common/details.dart index bf1c834..deff81c 100644 --- a/lib/templates/3-column/common/details.dart +++ b/lib/templates/3-column/common/details.dart @@ -5,7 +5,6 @@ import '../three_column_navigation.dart'; class DetailsView extends StatelessWidget { const DetailsView({ Key? key, - required int listIndex, required DetailsWidget details, this.previous, this.next, @@ -14,11 +13,10 @@ class DetailsView extends StatelessWidget { this.automaticallyImplyLeading = true, this.showDetailsArrows = false, this.scaffoldKey, - }) : _listIndex = listIndex, + }) : _details = details, super(key: key); - final int _listIndex; final DetailsWidget _details; final VoidCallback? previous, next; final bool showDetailsArrows; diff --git a/lib/templates/3-column/three_column_navigation.dart b/lib/templates/3-column/three_column_navigation.dart index b0ca728..bb67982 100644 --- a/lib/templates/3-column/three_column_navigation.dart +++ b/lib/templates/3-column/three_column_navigation.dart @@ -7,7 +7,7 @@ import 'package:scroll_to_index/scroll_to_index.dart'; import 'common/index.dart'; class ThreeColumnNavigation extends StatefulWidget { - ThreeColumnNavigation({ + const ThreeColumnNavigation({ Key? key, required this.sections, this.showDetailsArrows = true, @@ -23,7 +23,7 @@ class ThreeColumnNavigation extends StatefulWidget { final Widget? bottomAppBar; final IconData expandedIconData, collapsedIconData; final bool initiallyExpanded; - List sections; + final List sections; final bool showDetailsArrows; final Text? title; @@ -190,7 +190,6 @@ class _ThreeColumnNavigationState extends State { isFirst: _listIndex == 0, isLast: widget.sections[_sectionIndex].itemCount == _listIndex + 1, - listIndex: _listIndex, details: widget.sections[_sectionIndex] .getDetails(context, _listIndex), showDetailsArrows: widget.showDetailsArrows, @@ -257,7 +256,6 @@ class _ThreeColumnNavigationState extends State { isFirst: _listIndex == 0, isLast: widget.sections.isNotEmpty && _listIndex == widget.sections.length - 1, - listIndex: _listIndex, details: _details, // showDetailsArrows: false, ); @@ -288,7 +286,7 @@ class MenuButton extends StatelessWidget { icon: const Icon(Icons.menu), onPressed: () { Scaffold.of(context).openDrawer(); - // _scaffoldKey.currentState.showBodyScrim(true, 0.5); + _scaffoldKey.currentState?.showBodyScrim(true, 0.5); }, ); } diff --git a/lib/templates/list/responsive_list.dart b/lib/templates/list/responsive_list.dart index d1594ae..c5c68ad 100644 --- a/lib/templates/list/responsive_list.dart +++ b/lib/templates/list/responsive_list.dart @@ -243,4 +243,4 @@ class ResponsiveListScaffold extends StatelessWidget { } typedef DetailWidgetBuilder = DetailsScreen Function( - BuildContext context, int? index, bool tablet); + BuildContext context, int index, bool tablet); diff --git a/lib/templates/list/views/tablet.dart b/lib/templates/list/views/tablet.dart index 1e76881..6db8b74 100644 --- a/lib/templates/list/views/tablet.dart +++ b/lib/templates/list/views/tablet.dart @@ -251,7 +251,7 @@ class _TabletViewState extends State { details: _index == null || _index! > widget.childDelagate.estimatedChildCount! - 1 ? null - : widget.detailBuilder(context, _index, true), + : widget.detailBuilder(context, _index!, true), itemNotSelected: widget.itemNotSelected, ), ),