Skip to content
This repository was archived by the owner on Dec 5, 2023. It is now read-only.

Commit 1091530

Browse files
authored
Merge pull request #26 from Iconica-Development/feature/new_text_button_layout
feat: Added new button layout options for text button
2 parents ae72ec1 + ec0169c commit 1091530

File tree

5 files changed

+200
-38
lines changed

5 files changed

+200
-38
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
##[4.0.0] - 15 June 2023
2+
3+
* Added different button layout for text buttons.
4+
* ButtonBuilder now provides an extra paramter with the button type.
5+
16
##[3.0.0] - 2 June 2023
27

38
* Remove `rive` dependency

example/lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class MyApp extends StatelessWidget {
104104
buttonMode: IntroductionScreenButtonMode.text,
105105
indicatorMode: IndicatorMode.dash,
106106
skippable: true,
107-
buttonBuilder: (context, onPressed, child) =>
107+
buttonBuilder: (context, onPressed, child, buttonType) =>
108108
ElevatedButton(onPressed: onPressed, child: child),
109109
),
110110
onComplete: () {

lib/src/config/introduction.dart

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ enum IntroductionDisplayMode {
2121
multiPageHorizontal
2222
}
2323

24+
enum IntroductionControlMode {
25+
previousNextButton,
26+
singleButton,
27+
}
28+
29+
enum IntroductionButtonType {
30+
next,
31+
previous,
32+
finish,
33+
skip,
34+
}
35+
2436
class IntroductionPage {
2537
final Widget? title;
2638
final Widget? text;
@@ -98,9 +110,17 @@ class IntroductionOptions {
98110
///
99111
final IntroductionDisplayMode displayMode;
100112

113+
/// When [IntroductionDisplayMode.multiPageHorizontal] is selected multiple controlMode can be selected.
114+
/// [IntroductionControlMode.previousNextButton] shows two buttons at the bottom of the screen to return or proceed. The skip button is placed at the top left of the screen.
115+
/// [IntroductionControlMode.singleButton] contains one button at the bottom of the screen to proceed. Underneath is clickable text to skip if the current page is the first page. If the current page is any different it return to the previous screen.
116+
///
117+
final IntroductionControlMode controlMode;
118+
101119
/// A builder that can be used to replace the default text buttons when
102120
/// [IntroductionScreenButtonMode.text] is provided to [buttonMode]
103-
final Widget Function(BuildContext, VoidCallback, Widget)? buttonBuilder;
121+
final Widget Function(
122+
BuildContext, VoidCallback, Widget, IntroductionButtonType)?
123+
buttonBuilder;
104124

105125
/// The translations for all buttons on the introductionpages
106126
///
@@ -125,6 +145,7 @@ class IntroductionOptions {
125145
this.displayMode = IntroductionDisplayMode.multiPageHorizontal,
126146
this.skippable = false,
127147
this.buttonBuilder,
148+
this.controlMode = IntroductionControlMode.previousNextButton,
128149
}) : assert(
129150
!(identical(indicatorMode, IndicatorMode.custom) &&
130151
indicatorBuilder == null),

lib/src/types/page_introduction.dart

Lines changed: 171 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -101,28 +101,34 @@ class _MultiPageIntroductionScreenState
101101
child: Column(
102102
mainAxisAlignment: MainAxisAlignment.spaceBetween,
103103
children: [
104-
Padding(
105-
padding: const EdgeInsets.only(right: 16.0),
106-
child: SizedBox(
107-
height: 64,
108-
child: AnimatedBuilder(
109-
animation: _controller,
110-
builder: (context, _) {
111-
return Row(
112-
mainAxisAlignment: MainAxisAlignment.end,
113-
children: [
114-
if (widget.options.skippable && !_isLast(pages)) ...[
115-
TextButton(
116-
onPressed: widget.onComplete,
117-
child: Text(translations.skipButton),
118-
),
104+
if (widget.options.controlMode ==
105+
IntroductionControlMode.previousNextButton) ...[
106+
Padding(
107+
padding: const EdgeInsets.only(right: 16.0),
108+
child: SizedBox(
109+
height: 64,
110+
child: AnimatedBuilder(
111+
animation: _controller,
112+
builder: (context, _) {
113+
return Row(
114+
mainAxisAlignment: MainAxisAlignment.end,
115+
children: [
116+
if (widget.options.skippable &&
117+
!_isLast(pages)) ...[
118+
TextButton(
119+
onPressed: widget.onComplete,
120+
child: Text(translations.skipButton),
121+
),
122+
],
119123
],
120-
],
121-
);
122-
},
124+
);
125+
},
126+
),
123127
),
124128
),
125-
),
129+
] else ...[
130+
const SizedBox.shrink()
131+
],
126132
Align(
127133
alignment: Alignment.bottomCenter,
128134
child: Column(
@@ -141,20 +147,40 @@ class _MultiPageIntroductionScreenState
141147
padding: const EdgeInsets.all(32),
142148
child: AnimatedBuilder(
143149
animation: _controller,
144-
builder: (context, _) => IntroductionButtons(
145-
controller: _controller,
146-
next: _isNext(pages),
147-
previous: _isPrevious,
148-
last: _isLast(pages),
149-
options: widget.options,
150-
onFinish: widget.onComplete,
151-
onNext: () {
152-
widget.onNext?.call(pages[_currentPage.value]);
153-
},
154-
onPrevious: () {
155-
widget.onNext?.call(pages[_currentPage.value]);
156-
},
157-
),
150+
builder: (context, _) {
151+
if (widget.options.controlMode ==
152+
IntroductionControlMode.singleButton) {
153+
return IntroductionOneButton(
154+
controller: _controller,
155+
next: _isNext(pages),
156+
previous: _isPrevious,
157+
last: _isLast(pages),
158+
options: widget.options,
159+
onFinish: widget.onComplete,
160+
onNext: () {
161+
widget.onNext?.call(pages[_currentPage.value]);
162+
},
163+
onPrevious: () {
164+
widget.onNext?.call(pages[_currentPage.value]);
165+
},
166+
);
167+
}
168+
169+
return IntroductionTwoButtons(
170+
controller: _controller,
171+
next: _isNext(pages),
172+
previous: _isPrevious,
173+
last: _isLast(pages),
174+
options: widget.options,
175+
onFinish: widget.onComplete,
176+
onNext: () {
177+
widget.onNext?.call(pages[_currentPage.value]);
178+
},
179+
onPrevious: () {
180+
widget.onNext?.call(pages[_currentPage.value]);
181+
},
182+
);
183+
},
158184
),
159185
),
160186
],
@@ -261,8 +287,8 @@ class ExplainerPage extends StatelessWidget {
261287
}
262288
}
263289

264-
class IntroductionButtons extends StatelessWidget {
265-
const IntroductionButtons({
290+
class IntroductionTwoButtons extends StatelessWidget {
291+
const IntroductionTwoButtons({
266292
required this.options,
267293
required this.controller,
268294
required this.next,
@@ -306,6 +332,7 @@ class IntroductionButtons extends StatelessWidget {
306332
context,
307333
_previous,
308334
Text(translations.previousButton),
335+
IntroductionButtonType.previous,
309336
) ??
310337
TextButton(
311338
onPressed: _previous,
@@ -318,6 +345,7 @@ class IntroductionButtons extends StatelessWidget {
318345
context,
319346
_next,
320347
Text(translations.nextButton),
348+
IntroductionButtonType.next,
321349
) ??
322350
TextButton(
323351
onPressed: _next,
@@ -330,6 +358,7 @@ class IntroductionButtons extends StatelessWidget {
330358
onFinish?.call();
331359
},
332360
Text(translations.finishButton),
361+
IntroductionButtonType.finish,
333362
) ??
334363
TextButton(
335364
onPressed: () {
@@ -356,6 +385,7 @@ class IntroductionButtons extends StatelessWidget {
356385
onFinish?.call();
357386
},
358387
Text(translations.finishButton),
388+
IntroductionButtonType.finish,
359389
) ??
360390
ElevatedButton(
361391
onPressed: () {
@@ -381,6 +411,112 @@ class IntroductionButtons extends StatelessWidget {
381411
}
382412
}
383413

414+
class IntroductionOneButton extends StatelessWidget {
415+
const IntroductionOneButton({
416+
required this.options,
417+
required this.controller,
418+
required this.next,
419+
required this.last,
420+
required this.previous,
421+
required this.onFinish,
422+
required this.onNext,
423+
required this.onPrevious,
424+
Key? key,
425+
}) : super(key: key);
426+
427+
final IntroductionOptions options;
428+
final PageController controller;
429+
final VoidCallback? onFinish;
430+
final VoidCallback? onNext;
431+
final VoidCallback? onPrevious;
432+
433+
final bool previous;
434+
final bool next;
435+
final bool last;
436+
437+
void _previous() {
438+
controller.previousPage(
439+
duration: kAnimationDuration,
440+
curve: Curves.easeInOut,
441+
);
442+
onPrevious?.call();
443+
}
444+
445+
@override
446+
Widget build(BuildContext context) {
447+
var translations = options.introductionTranslations;
448+
449+
return Column(
450+
children: [
451+
if (options.buttonMode == IntroductionScreenButtonMode.text) ...[
452+
if (last) ...[
453+
options.buttonBuilder?.call(
454+
context,
455+
() {
456+
onFinish?.call();
457+
},
458+
Text(translations.finishButton),
459+
IntroductionButtonType.finish,
460+
) ??
461+
TextButton(
462+
onPressed: () {
463+
onFinish?.call();
464+
},
465+
child: Text(translations.finishButton),
466+
),
467+
] else ...[
468+
options.buttonBuilder?.call(
469+
context,
470+
_next,
471+
Text(translations.nextButton),
472+
IntroductionButtonType.next,
473+
) ??
474+
TextButton(
475+
onPressed: _next,
476+
child: Text(translations.nextButton),
477+
),
478+
],
479+
if (previous) ...[
480+
options.buttonBuilder?.call(
481+
context,
482+
_previous,
483+
Text(translations.previousButton),
484+
IntroductionButtonType.previous,
485+
) ??
486+
TextButton(
487+
onPressed: _previous,
488+
child: Text(translations.previousButton),
489+
),
490+
] else ...[
491+
options.buttonBuilder?.call(
492+
context,
493+
() {
494+
onFinish?.call();
495+
},
496+
Text(translations.finishButton),
497+
IntroductionButtonType.skip,
498+
) ??
499+
TextButton(
500+
onPressed: () {
501+
onFinish?.call();
502+
},
503+
child: Text(translations.finishButton),
504+
),
505+
],
506+
],
507+
],
508+
);
509+
}
510+
511+
_next() {
512+
controller.nextPage(
513+
duration: kAnimationDuration,
514+
curve: Curves.easeInOut,
515+
);
516+
onNext?.call();
517+
}
518+
}
519+
384520
class IntroductionIconButtons extends StatelessWidget {
385521
const IntroductionIconButtons({
386522
required this.options,

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flutter_introduction_widget
22
description: Flutter Introduction Widget for showing a list of introduction pages on a single scrollable page or horizontal pageview
3-
version: 3.0.0
3+
version: 4.0.0
44
homepage: https://github.com/Iconica-Development/flutter_introduction_widget
55

66
environment:

0 commit comments

Comments
 (0)