mirror of
https://github.com/Iconica-Development/flutter_form_wizard.git
synced 2025-05-19 19:03:47 +02:00
feat: improved example
This commit is contained in:
parent
11c8fcde73
commit
2741be487c
14 changed files with 167 additions and 148 deletions
|
@ -19,6 +19,8 @@ class AgePage {
|
|||
amountOfPages: amountOfPages,
|
||||
shellFormWidgets: [
|
||||
ShellFormInputNumberPicker(
|
||||
minValue: 12,
|
||||
maxValue: 120,
|
||||
controller: ShellFormInputNumberPickerController(
|
||||
id: "age",
|
||||
checkPageTitle: (dynamic amount) {
|
||||
|
|
|
@ -11,14 +11,14 @@ class CheckPageExample {
|
|||
return CheckPage(
|
||||
title: Container(
|
||||
margin: const EdgeInsets.only(
|
||||
top: 60,
|
||||
top: 70,
|
||||
bottom: 10,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
child: Text(
|
||||
checkPageText,
|
||||
child: const Text(
|
||||
"Check answers",
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
|
@ -30,7 +30,7 @@ class CheckPageExample {
|
|||
await onPressed();
|
||||
},
|
||||
child: Container(
|
||||
width: size.width * 0.9,
|
||||
width: MediaQuery.of(context).size.width * 0.9,
|
||||
padding: const EdgeInsets.only(
|
||||
top: 18,
|
||||
bottom: 16,
|
||||
|
@ -80,7 +80,7 @@ class CheckPageExample {
|
|||
if (description != null)
|
||||
Text(
|
||||
description,
|
||||
style: TextStyle(fontSize: fontSize / 1.3),
|
||||
style: const TextStyle(fontSize: 16),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
|
@ -18,6 +18,19 @@ class NamePage {
|
|||
amountOfPages: amountOfPages,
|
||||
title: "Please enter your name",
|
||||
shellFormWidgets: [
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.fromLTRB(40, 0, 40, 40),
|
||||
// child: ShellFormInputPlainText(
|
||||
// label: const Text("Name"),
|
||||
// controller: ShellFormInputPlainTextController(
|
||||
// mandatory: true,
|
||||
// id: "name",
|
||||
// checkPageTitle: (dynamic name) {
|
||||
// return "Name: $name";
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(40, 0, 40, 40),
|
||||
child: ShellFormInputPlainText(
|
||||
|
@ -31,19 +44,19 @@ class NamePage {
|
|||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(40, 0, 40, 0),
|
||||
child: ShellFormInputPlainText(
|
||||
label: const Text("Last Name"),
|
||||
controller: ShellFormInputPlainTextController(
|
||||
mandatory: true,
|
||||
id: "lastName",
|
||||
checkPageTitle: (dynamic lastName) {
|
||||
return "Last Name: $lastName";
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.fromLTRB(40, 0, 40, 0),
|
||||
// child: ShellFormInputPlainText(
|
||||
// label: const Text("Last Name"),
|
||||
// controller: ShellFormInputPlainTextController(
|
||||
// mandatory: true,
|
||||
// id: "lastName",
|
||||
// checkPageTitle: (dynamic lastName) {
|
||||
// return "Last Name: $lastName";
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -24,85 +24,88 @@ class _FormExampleState extends ConsumerState<FormExample> {
|
|||
var size = MediaQuery.of(context).size;
|
||||
var fontSize = size.height / 40;
|
||||
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: ShellForm(
|
||||
formController: formController,
|
||||
options: ShellFormOptions(
|
||||
onFinished: (Map<int, Map<String, dynamic>> results) {
|
||||
print("Totale resultaten: $results");
|
||||
Navigator.of(context).pushNamed('/thanks');
|
||||
},
|
||||
onNext: (int pageNumber, Map<String, dynamic> results) {
|
||||
print("Resultaten pagina $pageNumber: $results");
|
||||
},
|
||||
nextButton: (int pageNumber, bool checkingPages) {
|
||||
return Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: size.height / 20,
|
||||
),
|
||||
child: SizedBox(
|
||||
height: size.height / 15,
|
||||
width: size.width / 1.5,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
backgroundColor: Colors.black,
|
||||
textStyle: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
return GestureDetector(
|
||||
onTap: () => FocusScope.of(context).unfocus(),
|
||||
child: Scaffold(
|
||||
body: Center(
|
||||
child: ShellForm(
|
||||
formController: formController,
|
||||
options: ShellFormOptions(
|
||||
onFinished: (Map<int, Map<String, dynamic>> results) {
|
||||
print("Final full results: $results");
|
||||
Navigator.of(context).pushNamed('/thanks');
|
||||
},
|
||||
onNext: (int pageNumber, Map<String, dynamic> results) {
|
||||
print("Results page $pageNumber: $results");
|
||||
},
|
||||
nextButton: (int pageNumber, bool checkingPages) {
|
||||
return Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: size.height * 0.05,
|
||||
),
|
||||
child: SizedBox(
|
||||
height: size.height * 0.07,
|
||||
width: size.width * 0.7,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
backgroundColor: Colors.black,
|
||||
textStyle: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
formController.autoNextStep();
|
||||
},
|
||||
child: Text(checkingPages ? "Save" : "Next Page"),
|
||||
),
|
||||
onPressed: () {
|
||||
formController.autoNextStep();
|
||||
},
|
||||
child: Text(checkingPages ? "Save" : "Next Page"),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
backButton: (int pageNumber, bool checkingPages, int pageAmount) {
|
||||
if (pageNumber != 0) {
|
||||
if (!checkingPages || pageNumber >= pageAmount) {
|
||||
return Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(
|
||||
top: size.height / 20,
|
||||
left: size.width / 15,
|
||||
),
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(90),
|
||||
color: const Color(0xFFD8D8D8).withOpacity(0.50),
|
||||
),
|
||||
child: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
splashRadius: 29,
|
||||
onPressed: () {
|
||||
formController.previousStep();
|
||||
},
|
||||
icon: const Icon(Icons.chevron_left),
|
||||
)),
|
||||
);
|
||||
);
|
||||
},
|
||||
backButton: (int pageNumber, bool checkingPages, int pageAmount) {
|
||||
if (pageNumber != 0) {
|
||||
if (!checkingPages || pageNumber >= pageAmount) {
|
||||
return Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(
|
||||
top: size.height * 0.045,
|
||||
left: size.width * 0.07,
|
||||
),
|
||||
width: size.width * 0.08,
|
||||
height: size.width * 0.08,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(90),
|
||||
color: const Color(0xFFD8D8D8).withOpacity(0.50),
|
||||
),
|
||||
child: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
splashRadius: size.width * 0.06,
|
||||
onPressed: () {
|
||||
formController.previousStep();
|
||||
},
|
||||
icon: const Icon(Icons.chevron_left),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
pages: [
|
||||
AgePage().returnPage(size, fontSize, 1, 3),
|
||||
NamePage().returnPage(size, fontSize, 2, 3),
|
||||
CarouselPage().returnPage(size, fontSize, 3, 3),
|
||||
],
|
||||
checkPage: CheckPageExample()
|
||||
.showCheckpage(context, size, fontSize, checkPageText),
|
||||
return Container();
|
||||
},
|
||||
pages: [
|
||||
AgePage().returnPage(size, fontSize, 1, 3),
|
||||
// NamePage().returnPage(size, fontSize, 2, 3),
|
||||
CarouselPage().returnPage(size, fontSize, 3, 3),
|
||||
],
|
||||
checkPage: CheckPageExample()
|
||||
.showCheckpage(context, size, fontSize, checkPageText),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -20,50 +20,47 @@ class TemplatePage extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () => FocusScope.of(context).unfocus(),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: size.width / 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: size.height / 10,
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: size.width / 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: size.height / 10,
|
||||
),
|
||||
Text(
|
||||
"$pageNumber / $amountOfPages",
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
),
|
||||
Text(
|
||||
"$pageNumber / $amountOfPages",
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: size.height / 80,
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
SizedBox(
|
||||
height: size.height / 80,
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
for (var widget in shellFormWidgets) ...[
|
||||
widget,
|
||||
],
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
for (var widget in shellFormWidgets) ...[
|
||||
widget,
|
||||
],
|
||||
),
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ class ShellFormPage {
|
|||
});
|
||||
}
|
||||
|
||||
/// CheckPage is used to set a check page at the end of a [ShellForm].
|
||||
/// A CheckPage is a page where the user can check all input values before commiting.
|
||||
/// [CheckPage] is used to set a check page at the end of a [ShellForm].
|
||||
/// A [CheckPage] is a page where the user can check all input values before commiting.
|
||||
///
|
||||
/// [title] is the widget shown at the top of the page.
|
||||
///
|
||||
|
|
|
@ -25,7 +25,7 @@ import 'src/utils/formstate.dart' as fs;
|
|||
/// // print(results);
|
||||
/// },
|
||||
/// onNext: (int pageNumber, Map<String, dynamic> results) {
|
||||
/// // print("Resultaten pagina $pageNumber: $results");
|
||||
/// // print("Results page $pageNumber: $results");
|
||||
/// },
|
||||
/// nextButton: (int pageNumber, bool checkingPages) {
|
||||
/// return Align(
|
||||
|
@ -38,7 +38,7 @@ import 'src/utils/formstate.dart' as fs;
|
|||
/// onPressed: () {
|
||||
/// shellFormController.autoNextStep();
|
||||
/// },
|
||||
/// child: Text(checkingPages ? "Opslaan" : "Volgende stap"),
|
||||
/// child: Text(checkingPages ? "Save" : "Next Page"),
|
||||
/// ),
|
||||
/// ),
|
||||
/// );
|
||||
|
@ -100,7 +100,7 @@ import 'src/utils/formstate.dart' as fs;
|
|||
/// ],
|
||||
/// checkPage: CheckPage(
|
||||
/// title: const Text(
|
||||
/// "Hier zijn je wensen voor het afscheidsfeestje",
|
||||
/// "All entered info: ",
|
||||
/// style: TextStyle(
|
||||
/// fontSize: 25,
|
||||
/// fontWeight: FontWeight.w900,
|
||||
|
|
|
@ -73,7 +73,7 @@ class CarouselSliderState extends State<CarouselSlider>
|
|||
|
||||
PageController? pageController;
|
||||
|
||||
/// [mode] is related to why the page is being changed
|
||||
/// [mode] is related to why the page is being changed.
|
||||
CarouselPageChangedReason mode = CarouselPageChangedReason.controller;
|
||||
|
||||
CarouselSliderState();
|
||||
|
@ -87,14 +87,14 @@ class CarouselSliderState extends State<CarouselSlider>
|
|||
carouselState!.options = options;
|
||||
carouselState!.itemCount = widget.itemCount;
|
||||
|
||||
// pageController needs to be re-initialized to respond to state changes
|
||||
/// [pageController] needs to be re-initialized to respond to state changes.
|
||||
pageController = PageController(
|
||||
viewportFraction: options.viewportFraction,
|
||||
initialPage: carouselState!.realPage,
|
||||
);
|
||||
carouselState!.pageController = pageController;
|
||||
|
||||
// handle autoplay when state changes
|
||||
/// handle autoplay when state changes
|
||||
handleAutoPlay();
|
||||
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
@ -296,13 +296,13 @@ class CarouselSliderState extends State<CarouselSlider>
|
|||
: widget.itemBuilder!(context, index, idx),
|
||||
builder: (BuildContext context, child) {
|
||||
double distortionValue = 1.0;
|
||||
// if `enlargeCenterPage` is true, we must calculate the carousel item's height
|
||||
// if [enlargeCenterPage] is true, we must calculate the carousel item's height
|
||||
// to display the visual effect
|
||||
|
||||
if (widget.options.enlargeCenterPage != null &&
|
||||
widget.options.enlargeCenterPage == true) {
|
||||
// pageController.page can only be accessed after the first build,
|
||||
// so in the first build we calculate the itemoffset manually
|
||||
// [pageController.page] can only be accessed after the first build,
|
||||
// so in the first build we calculate the [itemOffset] manually
|
||||
double itemOffset = 0;
|
||||
var position = carouselState?.pageController?.position;
|
||||
if (position != null &&
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
///
|
||||
/// For example; We have a Carousel of 10000(simulating infinity) but only 6 images.
|
||||
/// We need to repeat the images to give the illusion of a never ending stream.
|
||||
/// By calling _getRealIndex with position and base we get an offset.
|
||||
/// By calling [getRealIndex] with position and base we get an offset.
|
||||
/// This offset modulo our length, 6, will return a number between 0 and 5, which represent the image
|
||||
/// to be placed in the given position.
|
||||
int getRealIndex(int position, int base, int? length) {
|
||||
|
|
|
@ -8,7 +8,7 @@ import 'carousel_form.dart';
|
|||
|
||||
/// Input for a carousel of items used in a [ShellForm].
|
||||
///
|
||||
/// items will be the [Widget]s to be displayed in the carousel.
|
||||
/// [items] will be the [Widget]s to be displayed in the carousel.
|
||||
///
|
||||
/// Standard controller is [ShellFormInputCarouselController].
|
||||
class ShellFormInputCarousel extends ShellFormInputWidget {
|
||||
|
@ -37,7 +37,7 @@ class ShellFormInputCarousel extends ShellFormInputWidget {
|
|||
}
|
||||
}
|
||||
|
||||
/// Controller for the carousel used by a [ShellFormInputWidget] used in a [ShellFrom].
|
||||
/// Controller for the carousel used by a [ShellFormInputWidget] used in a [ShellForm].
|
||||
///
|
||||
/// Mainly used by [ShellFormInputCarousel].
|
||||
class ShellFormInputCarouselController
|
||||
|
|
|
@ -39,7 +39,7 @@ class ShellFormInputEmail extends ShellFormInputWidget {
|
|||
}
|
||||
}
|
||||
|
||||
/// Controller for emails used by a [ShellFormInputWidget] used in a [ShellFrom].
|
||||
/// Controller for emails used by a [ShellFormInputWidget] used in a [ShellForm].
|
||||
///
|
||||
/// Mainly used by [ShellFormInputEmail].
|
||||
class ShellFormInputEmailController
|
||||
|
|
|
@ -26,9 +26,11 @@ class ShellFormInputNumberPicker extends ShellFormInputWidget {
|
|||
super.registerController(context);
|
||||
|
||||
return NumberPickerFormField(
|
||||
minValue: minValue,
|
||||
maxValue: maxValue,
|
||||
onSaved: (value) => controller.onSaved(value),
|
||||
validator: (value) => controller.onValidate(value, _),
|
||||
initialValue: controller.value ?? 0,
|
||||
initialValue: controller.value ?? minValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Creates a slider with the given input parameters
|
||||
class SliderFormField extends FormField<double> {
|
||||
SliderFormField({
|
||||
Key? key,
|
||||
|
|
1
test/flutter_form_tests.dart
Normal file
1
test/flutter_form_tests.dart
Normal file
|
@ -0,0 +1 @@
|
|||
|
Loading…
Reference in a new issue