diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d96eba..5d6406d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [0.4.0] - 29.09.2023 + +- New properties `showNextButton` and `showPrevButton` for showing/hiding the next/prev buttons +- New way to customize prev/next buttons using `prevButtonBuilder` or `nextButtonBuilder` +- Slight adaptation of margin/padding of "three dots" (only noticeable if it's background is colored) + ## [0.3.2] - 30.07.2023 - Correct images in README.md diff --git a/README.md b/README.md index d98541f..1ab9ca4 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,8 @@ floatingActionButton: FloatingActionButton( ### Customize `NumberPaginator` allows for several customizations. + +#### Button look and feel ```dart NumberPaginator( // by default, the paginator shows numbers as center content @@ -85,6 +87,37 @@ NumberPaginator( custom buttons

+#### Visibility/customisation of prev/next buttons +```dart +NumberPaginator( + // by default, the paginator shows numbers as center content + numberPages: 10, + onPageChange: (int index) { + setState(() { + _currentPage = index; // _currentPage is a variable within State of StatefulWidget + }); + }, + // show/hide the prev/next buttons + showPrevButton: true, + showNextButton: false, // defaults to true + // custom content of the prev/next buttons, maintains their behavior + nextButtonContent: Icon(Icons.arrow_right_alt), + // custom prev/next buttons using builder (ignored if showPrevButton/showNextButton is false) + prevButtonBuilder: (context) => TextButton( + onPressed: _controller.currentPage > 0 ? () => _controller.prev() : null, // _controller must be passed to NumberPaginator + child: const Row( + children: [ + Icon(Icons.chevron_left), + Text("Previous"), + ], + ), + ), +) +``` +

+ prev/next button customisation +

+ ### Content variations The new version of `NumberPaginator` allows for further customization of how a user can navigate between pages. It provides three different modes and an additional possibility of complete customization o the content using a `builder`. diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 59260ed..6b8f839 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -127,7 +127,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 3db53b6..b52b2e6 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ =3.0.0-0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=1.17.0" diff --git a/lib/src/ui/number_paginator.dart b/lib/src/ui/number_paginator.dart index 2a6140e..b4de1bb 100644 --- a/lib/src/ui/number_paginator.dart +++ b/lib/src/ui/number_paginator.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:number_paginator/src/model/config.dart'; import 'package:number_paginator/src/model/display_mode.dart'; import 'package:number_paginator/src/ui/number_paginator_controller.dart'; -import 'package:number_paginator/src/ui/widgets/buttons/paginator_icon_button.dart'; +import 'package:number_paginator/src/ui/widgets/buttons/paginator_button.dart'; import 'package:number_paginator/src/ui/widgets/inherited_number_paginator.dart'; import 'package:number_paginator/src/ui/widgets/paginator_content.dart'; @@ -27,8 +27,48 @@ class NumberPaginator extends StatefulWidget { /// [config] is ignored. final NumberPaginatorContentBuilder? contentBuilder; + /// The controller for the paginator. Can be used to control the paginator from the outside. + /// If not provided, a new controller is created. final NumberPaginatorController? controller; + /// Whether the "prev" button should be shown. + /// + /// Defaults to `true`. + final bool showPrevButton; + + /// Whether the "next" button should be shown. + /// + /// Defaults to `true`. + final bool showNextButton; + + /// Content of the "previous" button which when pressed goes one page back. + /// + /// Defaults to: + /// ```dart + /// Icon(Icons.chevron_left), + /// ``` + final Widget prevButtonContent; + + /// Content of the "next" button which when pressed goes one page forward. + /// + /// Defaults to: + /// ```dart + /// Icon(Icons.chevron_right), + /// ``` + final Widget nextButtonContent; + + /// Builder option for providing a custom "previous" button. + /// + /// If this is provided, [prevButtonContent] is ignored. + /// If [showPrevButton] is `false`, this is ignored. + final WidgetBuilder? prevButtonBuilder; + + /// Builder option for providing a custom "next" button. + /// + /// If this is provided, [nextButtonContent] is ignored. + /// If [showNextButton] is `false`, this is ignored. + final WidgetBuilder? nextButtonBuilder; + /// Creates an instance of [NumberPaginator]. const NumberPaginator({ Key? key, @@ -38,10 +78,34 @@ class NumberPaginator extends StatefulWidget { this.config = const NumberPaginatorUIConfig(), this.contentBuilder, this.controller, + this.showPrevButton = true, + this.showNextButton = true, + this.prevButtonContent = const Icon(Icons.chevron_left), + this.nextButtonContent = const Icon(Icons.chevron_right), + this.prevButtonBuilder, + this.nextButtonBuilder, }) : assert(initialPage >= 0), assert(initialPage <= numberPages - 1), super(key: key); + const NumberPaginator.noPrevNextButtons({ + Key? key, + required this.numberPages, + this.initialPage = 0, + this.onPageChange, + this.config = const NumberPaginatorUIConfig(), + this.contentBuilder, + this.controller, + }) : showPrevButton = false, + showNextButton = false, + prevButtonContent = const SizedBox(), + nextButtonContent = const SizedBox(), + prevButtonBuilder = null, + nextButtonBuilder = null, + assert(initialPage >= 0), + assert(initialPage <= numberPages - 1), + super(key: key); + @override NumberPaginatorState createState() => NumberPaginatorState(); } @@ -72,17 +136,20 @@ class NumberPaginatorState extends State { child: Row( mainAxisAlignment: widget.config.mainAxisAlignment, children: [ - PaginatorIconButton( - onPressed: _controller.currentPage > 0 ? _controller.prev : null, - icon: Icons.chevron_left, - ), + if (widget.showPrevButton) + widget.prevButtonBuilder?.call(context) ?? + PaginatorButton( + onPressed: _controller.currentPage > 0 ? _controller.prev : null, + child: widget.prevButtonContent, + ), ..._buildCenterContent(), - PaginatorIconButton( - onPressed: _controller.currentPage < widget.numberPages - 1 - ? _controller.next - : null, - icon: Icons.chevron_right, - ), + if (widget.showNextButton) + widget.nextButtonBuilder?.call(context) ?? + PaginatorButton( + onPressed: + _controller.currentPage < widget.numberPages - 1 ? _controller.next : null, + child: widget.nextButtonContent, + ), ], ), ), diff --git a/lib/src/ui/widgets/buttons/paginator_icon_button.dart b/lib/src/ui/widgets/buttons/paginator_icon_button.dart deleted file mode 100644 index 8dbc9a8..0000000 --- a/lib/src/ui/widgets/buttons/paginator_icon_button.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:number_paginator/src/ui/widgets/buttons/paginator_button.dart'; - -/// A paginator button that has an [Icon] as a child, instead of text. The icon -/// scales with the available space, depending on the size of the button. -class PaginatorIconButton extends StatelessWidget { - final IconData icon; - final VoidCallback? onPressed; - - const PaginatorIconButton({ - Key? key, - required this.icon, - this.onPressed, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return PaginatorButton( - onPressed: onPressed, - // size icon depending on available height - child: FittedBox( - child: Icon(icon), - ), - ); - } -} diff --git a/lib/src/ui/widgets/paginator_content/number_content.dart b/lib/src/ui/widgets/paginator_content/number_content.dart index 5cceec0..387a8b9 100644 --- a/lib/src/ui/widgets/paginator_content/number_content.dart +++ b/lib/src/ui/widgets/paginator_content/number_content.dart @@ -26,15 +26,12 @@ class NumberContent extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildPageButton(context, 0), - if (_frontDotsShouldShow(context, availableSpots)) - _buildDots(context), + if (_frontDotsShouldShow(context, availableSpots)) _buildDots(context), if (InheritedNumberPaginator.of(context).numberPages > 1) ..._generateButtonList(context, availableSpots), - if (_backDotsShouldShow(context, availableSpots)) - _buildDots(context), + if (_backDotsShouldShow(context, availableSpots)) _buildDots(context), if (InheritedNumberPaginator.of(context).numberPages > 1) - _buildPageButton(context, - InheritedNumberPaginator.of(context).numberPages - 1), + _buildPageButton(context, InheritedNumberPaginator.of(context).numberPages - 1), ], ); }, @@ -59,38 +56,31 @@ class NumberContent extends StatelessWidget { minValue = (maxValue - shownPages).clamp(1, numberPages - 1); } - return List.generate(maxValue - minValue, - (index) => _buildPageButton(context, minValue + index)); + return List.generate( + maxValue - minValue, (index) => _buildPageButton(context, minValue + index)); } /// Builds a button for the given index. Widget _buildPageButton(BuildContext context, int index) => PaginatorButton( - onPressed: () => - InheritedNumberPaginator.of(context).onPageChange?.call(index), + onPressed: () => InheritedNumberPaginator.of(context).onPageChange?.call(index), selected: _selected(index), - child: - AutoSizeText((index + 1).toString(), maxLines: 1, minFontSize: 5), + child: AutoSizeText((index + 1).toString(), maxLines: 1, minFontSize: 5), ); Widget _buildDots(BuildContext context) => AspectRatio( aspectRatio: 1, child: Container( - // padding: const EdgeInsets.all(4.0), - margin: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(4.0), + margin: const EdgeInsets.all(4.0), alignment: Alignment.bottomCenter, decoration: ShapeDecoration( - shape: InheritedNumberPaginator.of(context).config.buttonShape ?? - const CircleBorder(), - color: InheritedNumberPaginator.of(context) - .config - .buttonUnselectedBackgroundColor, + shape: InheritedNumberPaginator.of(context).config.buttonShape ?? const CircleBorder(), + color: InheritedNumberPaginator.of(context).config.buttonUnselectedBackgroundColor, ), child: AutoSizeText( "...", style: TextStyle( - color: InheritedNumberPaginator.of(context) - .config - .buttonUnselectedForegroundColor ?? + color: InheritedNumberPaginator.of(context).config.buttonUnselectedForegroundColor ?? Theme.of(context).colorScheme.secondary, fontSize: 16, fontWeight: FontWeight.bold, @@ -102,9 +92,7 @@ class NumberContent extends StatelessWidget { /// Checks if pages don't fit in available spots and dots have to be shown. bool _backDotsShouldShow(BuildContext context, int availableSpots) => availableSpots < InheritedNumberPaginator.of(context).numberPages && - currentPage < - InheritedNumberPaginator.of(context).numberPages - - availableSpots ~/ 2; + currentPage < InheritedNumberPaginator.of(context).numberPages - availableSpots ~/ 2; bool _frontDotsShouldShow(BuildContext context, int availableSpots) => availableSpots < InheritedNumberPaginator.of(context).numberPages && diff --git a/pubspec.lock b/pubspec.lock index 373dd73..9f9c74a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" fake_async: dependency: transitive description: @@ -66,23 +66,15 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" lints: dependency: transitive description: @@ -95,18 +87,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -132,10 +124,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -172,10 +164,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" vector_math: dependency: transitive description: @@ -184,6 +176,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=1.17.0" diff --git a/pubspec.yaml b/pubspec.yaml index 31aac87..3f0f193 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: number_paginator description: A Flutter paginator widget for switching between page numbers. -version: 0.3.2 +version: 0.4.0 homepage: https://github.com/WieFel/number_paginator environment: