diff --git a/CHANGELOG.md b/CHANGELOG.md index e52db10..6a48dcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.3.0 +* Customizable animation duration +* New and improved example +* More customization options and improved looks + ## 2.2.0 * Added subtitles for masterItem * You can now also customize the app bar size in master view when collapsed diff --git a/README.md b/README.md index b8ce0c3..14b19eb 100644 --- a/README.md +++ b/README.md @@ -63,4 +63,4 @@ In the example app you can find examples of how to create: Also you should read https://pub.dev/documentation/master_detail_flow/latest/ -![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s2.png?raw=true)![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s3.png?raw=true)![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s4.png?raw=true)![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s5.png?raw=true) \ No newline at end of file +![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s2.png?raw=true) ![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s3.png?raw=true) ![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s4.png?raw=true) ![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s5.png?raw=true) ![Screeshot](https://github.com/2-5-perceivers/flutter-master-detail-flow/blob/master/images/s6.png?raw=true) \ No newline at end of file diff --git a/example/lib/widgets/label.dart b/example/lib/widgets/label.dart index 884fdc6..266be74 100644 --- a/example/lib/widgets/label.dart +++ b/example/lib/widgets/label.dart @@ -1,8 +1,8 @@ - import 'package:flutter/material.dart'; class LabelText extends StatelessWidget { - const LabelText(this.data, { + const LabelText( + this.data, { super.key, }); diff --git a/example/pubspec.lock b/example/pubspec.lock index 611cd2b..d199257 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -54,7 +54,7 @@ packages: path: ".." relative: true source: path - version: "2.2.0" + version: "2.3.0" material_color_utilities: dependency: transitive description: diff --git a/images/s6.png b/images/s6.png new file mode 100644 index 0000000..a27d77b Binary files /dev/null and b/images/s6.png differ diff --git a/lib/src/master_item.dart b/lib/src/master_item.dart index ab062c0..afb3dca 100644 --- a/lib/src/master_item.dart +++ b/lib/src/master_item.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; import 'package:master_detail_flow/src/typedefs.dart'; -/// a base for items +/// A base for items. Implement this in a Widget class to create a custom +/// master item abstract class MasterItemBase { /// Default constructor const MasterItemBase(); @@ -52,42 +53,60 @@ class MasterItem extends MasterItemBase { final GestureTapCallback? onTap; } -/// A master item that acts as a header +/// A master item that acts as a header.. class MasterItemHeader extends StatelessWidget implements MasterItemBase { /// Creates a header const MasterItemHeader({ required this.child, + this.cardPadding, + this.cardElevation = 2, super.key, }); /// The child of final Widget child; + /// A padding to be put arround the card. + /// + /// Defaults to `EdgeInsets.symmetric(horizontal: 16, vertical: 8,)`. + final EdgeInsetsGeometry? cardPadding; + + /// The card elevation. + /// + /// Defaults to 2. + final double cardElevation; + @override Widget build(BuildContext context) { - return SizedBox( - height: 200, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Card( - elevation: 2, - child: child, - ), + return ConstrainedBox( + constraints: const BoxConstraints( + minHeight: 200, + ), + child: Card( + margin: cardPadding ?? + const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + elevation: cardElevation, + child: child, ), ); } } -/// A divider for the master list +/// A divider for the master list. That get's its indent from the listTileTheme +/// in order to arrange with the list tiles class MasterItemDivider extends StatelessWidget implements MasterItemBase { /// Creates a divider const MasterItemDivider({super.key}); @override Widget build(BuildContext context) { - return const Divider( - indent: 12, - endIndent: 12, + final ListTileThemeData listTileTheme = ListTileTheme.of(context); + return Divider( + indent: listTileTheme.contentPadding?.horizontal ?? 16, + endIndent: listTileTheme.contentPadding?.horizontal ?? 16, ); } } diff --git a/lib/src/widget.dart b/lib/src/widget.dart index fc9ef33..924959b 100644 --- a/lib/src/widget.dart +++ b/lib/src/widget.dart @@ -13,7 +13,11 @@ class MasterDetailsFlow extends StatefulWidget { required this.items, this.actions, this.autoImplyLeading = true, + this.breakpoint = 700, this.initialPage, + this.lateralMasterPanelWidth = 300.0, + this.detailsPanelCornersRadius = 12.0, + this.lateralListTileTheme, this.title, this.nothingSelectedWidget, this.lateralDetailsAppBar = DetailsAppBarSize.medium, @@ -37,6 +41,25 @@ class MasterDetailsFlow extends StatefulWidget { /// If leading widget is not null, this parameter has no effect. final bool autoImplyLeading; + /// If the screen width is larger than breakpoint it moves to lateral view, + /// otherwise is in page mode. + /// + /// Defaults to 700. + final int breakpoint; + + /// The width of the lateral panel that hold the tiles. + /// + /// Defaults to 300.0 + final double lateralMasterPanelWidth; + + /// The corners radius of the details panel + /// + /// Defaults to 12 + final double detailsPanelCornersRadius; + + /// The theme used by the selectable tiles on the lateral panel + final ListTileThemeData? lateralListTileTheme; + /// The option title to be showed on the master app bar. final Widget? title; @@ -99,7 +122,7 @@ class _MasterDetailsFlowState extends State { final ColorScheme colorScheme = theme.colorScheme; final double screenWidth = MediaQuery.of(context).size.width; - final bool large = screenWidth >= 700; + final bool large = screenWidth >= widget.breakpoint; if (large) { return Scaffold( @@ -109,23 +132,24 @@ class _MasterDetailsFlowState extends State { mainAxisSize: MainAxisSize.max, children: [ Container( - constraints: const BoxConstraints( - maxWidth: 300, + constraints: BoxConstraints( + maxWidth: widget.lateralMasterPanelWidth, ), child: ListTileTheme( - data: ListTileThemeData( - selectedColor: colorScheme.onSecondaryContainer, - selectedTileColor: colorScheme.secondaryContainer, - iconColor: colorScheme.onSurfaceVariant, - textColor: colorScheme.onSurface, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - contentPadding: const EdgeInsetsDirectional.only( - start: 16, - end: 24, - ), - ), + data: widget.lateralListTileTheme ?? + ListTileThemeData( + selectedColor: colorScheme.onSecondaryContainer, + selectedTileColor: colorScheme.secondaryContainer, + iconColor: colorScheme.onSurfaceVariant, + textColor: colorScheme.onSurface, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(28), + ), + contentPadding: const EdgeInsetsDirectional.only( + start: 16, + end: 24, + ), + ), style: ListTileStyle.drawer, child: ListView.builder( itemBuilder: (BuildContext context, int index) { @@ -138,8 +162,10 @@ class _MasterDetailsFlowState extends State { } final MasterItem item = itemBase as MasterItem; return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, + padding: EdgeInsets.symmetric( + horizontal: + theme.listTileTheme.contentPadding?.horizontal ?? + 16, vertical: 2, ), child: listTileBuilder(item), @@ -168,9 +194,9 @@ class _MasterDetailsFlowState extends State { end: 12, ), child: Material( - shape: const RoundedRectangleBorder( + shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical( - top: Radius.circular(12), + top: Radius.circular(widget.detailsPanelCornersRadius), ), ), color: ElevationOverlay.applySurfaceTint( @@ -261,8 +287,6 @@ class _MasterDetailsFlowState extends State { }) { final Widget? subtitle = item.subtitle != null ? Text(item.subtitle!) : null; - final EdgeInsets? contentPadding = - (page && item.subtitle == null) ? const EdgeInsets.all(8) : null; return ListTile( title: Text(item.title), @@ -270,7 +294,6 @@ class _MasterDetailsFlowState extends State { leading: item.leading, trailing: item.trailing, selected: (selectedItem?.title == item.title) && !page, - contentPadding: contentPadding, onTap: item.onTap ?? () { setState(() { diff --git a/pubspec.yaml b/pubspec.yaml index 74880cc..b31ae53 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: master_detail_flow description: A package that provides a simple master-detail-flow with material 3 -version: 2.2.0 +version: 2.3.0 repository: https://github.com/2-5-perceivers/flutter-master-detail-flow environment: