节省小部件在步进
我创建了一个步进器(4 个步骤),其中有两个按钮用于下一个和上一个。每个步骤都有一个表单,每个表单都位于其自己类的小部件中。
第一个问题是,每次单击上一个按钮时,文本字段中的数据都会消失。 如何在每个步骤中保留每个小部件的状态?
第二个问题,我希望最后一步是用户在前面步骤中输入的内容的摘要。从每个步骤获取数据并在最后一步显示它们的最佳方法是什么?
如果您能给我一个解决方案,我将非常感激。谢谢
我尝试使用AutomaticKeepAliveClientMixin,但它不起作用。
import 'package:flutter/material.dart';
class CustomeStepper extends StatelessWidget {
final double width;
final List<IconData> icons;
final List<String> titles;
final int curStep;
final Color circleActiveColor;
final Color circleInactiveColor;
final Color iconActiveColor;
final Color iconInactiveColor;
final Color textActiveColor;
final Color textInactiveColor;
final double lineWidth = 4.0;
final List<Widget> content;
CustomeStepper(
{required this.icons,
required this.curStep,
required this.titles,
required this.width,
required this.circleActiveColor,
required this.circleInactiveColor,
required this.iconActiveColor,
required this.iconInactiveColor,
required this.textActiveColor,
required this.textInactiveColor,
required this.content})
: assert(curStep > 0 && curStep <= icons.length),
assert(width > 0);
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Container(
width: width,
padding: const EdgeInsets.only(
top: 32.0,
left: 24.0,
right: 24.0,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
children: _iconViews(),
),
const SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: _titleViews(),
),
Expanded(
child: Container(
margin: const EdgeInsets.only(top: 16),
child: content[curStep - 1]),
)
],
)),
);
}
List<Widget> _iconViews() {
var list = <Widget>[];
icons.asMap().forEach((i, icon) {
var circleColor = (i == 0 || curStep >= i + 1)
? circleActiveColor
: circleInactiveColor;
var lineColor = (i == 0 || curStep >= i + 1)
? circleActiveColor
: circleInactiveColor;
var iconColor =
(i == 0 || curStep >= i + 1) ? iconActiveColor : iconInactiveColor;
list.add(
Container(
width: 50.0,
height: 50.0,
padding: const EdgeInsets.all(0),
child: Icon(
icon,
color: iconColor,
size: 25.0,
),
decoration: BoxDecoration(
color: circleColor,
borderRadius: const BorderRadius.all(
Radius.circular(25.0),
),
),
),
);
//line between icons
if (i != icons.length - 1) {
list.add(Expanded(
child: Container(
height: lineWidth,
color: lineColor,
)));
}
});
return list;
}
List<Widget> _titleViews() {
var list = <Widget>[];
titles.asMap().forEach((i, text) {
var _textColor =
(i == 0 || curStep > i + 1) ? textActiveColor : textInactiveColor;
list.add(
Container(
width: 50.0,
alignment: Alignment.topCenter,
padding: const EdgeInsets.all(0),
child: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(color: _textColor, fontWeight: FontWeight.bold),
),
),
);
});
return list;
}
}
import 'package:flutter/material.dart';
import 'package:project_five/widgets/business/adding_product_widgets/first_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/four_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/second_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/third_step.dart';
import 'package:project_five/widgets/business/custome_stepper.dart';
class AddProduct extends StatefulWidget {
const AddProduct({Key? key}) : super(key: key);
@override
State<AddProduct> createState() => _AddProductState();
}
class _AddProductState extends State<AddProduct> {
static const _stepIcons = [
Icons.add_circle,
Icons.document_scanner,
Icons.camera_alt_rounded,
Icons.check,
];
static const _titles = ['المنتج', 'تفاصيل', 'الصور', 'نشر'];
var _contnet = [
FirstStep(),
SecondStep(),
ThirdStep(),
Forth()];
var _curStep = 1;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('إضافة منتج'),
centerTitle: true,
),
persistentFooterButtons: [
Row(
children: [
Expanded(
child: ElevatedButton(
child: const Text('التالي'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(16),
),
onPressed: () => setState(() {
if (_curStep < _stepIcons.length) _curStep++;
}),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: ElevatedButton(
child: const Text('رجوع'),
style: ElevatedButton.styleFrom(
primary: Colors.white,
onPrimary: Colors.black,
padding: const EdgeInsets.all(16)),
onPressed: () => setState(() {
if (_curStep > 1) _curStep--;
}),
),
),
],
)
],
body: CustomeStepper(
icons: _stepIcons,
width: MediaQuery.of(context).size.width,
curStep: _curStep,
titles: _titles,
circleActiveColor: Colors.green,
circleInactiveColor: const Color(0xffD5D5D5),
iconActiveColor: Colors.white,
iconInactiveColor: Colors.white,
textActiveColor: Colors.green,
textInactiveColor: const Color(0xffD5D5D5),
content: _contnet,
),
);
}
}
I created a stepper (4 steps) with two buttons for next and previous. Each step has a form, and each form is in a widget in its own class.
The first problem is that every time I click the previous button, the data in the text fields disappear.
How can I preserve the state of each widget in each step?
The second problem, I want the last step to be a summary of what the user has entered in the previous steps. What is the best way to get the data from each step and display them in the last step?
I would really appreciate it if you could give me a solution. Thank you
I tried using AutomaticKeepAliveClientMixin but it didn't work .
import 'package:flutter/material.dart';
class CustomeStepper extends StatelessWidget {
final double width;
final List<IconData> icons;
final List<String> titles;
final int curStep;
final Color circleActiveColor;
final Color circleInactiveColor;
final Color iconActiveColor;
final Color iconInactiveColor;
final Color textActiveColor;
final Color textInactiveColor;
final double lineWidth = 4.0;
final List<Widget> content;
CustomeStepper(
{required this.icons,
required this.curStep,
required this.titles,
required this.width,
required this.circleActiveColor,
required this.circleInactiveColor,
required this.iconActiveColor,
required this.iconInactiveColor,
required this.textActiveColor,
required this.textInactiveColor,
required this.content})
: assert(curStep > 0 && curStep <= icons.length),
assert(width > 0);
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Container(
width: width,
padding: const EdgeInsets.only(
top: 32.0,
left: 24.0,
right: 24.0,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
children: _iconViews(),
),
const SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: _titleViews(),
),
Expanded(
child: Container(
margin: const EdgeInsets.only(top: 16),
child: content[curStep - 1]),
)
],
)),
);
}
List<Widget> _iconViews() {
var list = <Widget>[];
icons.asMap().forEach((i, icon) {
var circleColor = (i == 0 || curStep >= i + 1)
? circleActiveColor
: circleInactiveColor;
var lineColor = (i == 0 || curStep >= i + 1)
? circleActiveColor
: circleInactiveColor;
var iconColor =
(i == 0 || curStep >= i + 1) ? iconActiveColor : iconInactiveColor;
list.add(
Container(
width: 50.0,
height: 50.0,
padding: const EdgeInsets.all(0),
child: Icon(
icon,
color: iconColor,
size: 25.0,
),
decoration: BoxDecoration(
color: circleColor,
borderRadius: const BorderRadius.all(
Radius.circular(25.0),
),
),
),
);
//line between icons
if (i != icons.length - 1) {
list.add(Expanded(
child: Container(
height: lineWidth,
color: lineColor,
)));
}
});
return list;
}
List<Widget> _titleViews() {
var list = <Widget>[];
titles.asMap().forEach((i, text) {
var _textColor =
(i == 0 || curStep > i + 1) ? textActiveColor : textInactiveColor;
list.add(
Container(
width: 50.0,
alignment: Alignment.topCenter,
padding: const EdgeInsets.all(0),
child: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(color: _textColor, fontWeight: FontWeight.bold),
),
),
);
});
return list;
}
}
import 'package:flutter/material.dart';
import 'package:project_five/widgets/business/adding_product_widgets/first_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/four_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/second_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/third_step.dart';
import 'package:project_five/widgets/business/custome_stepper.dart';
class AddProduct extends StatefulWidget {
const AddProduct({Key? key}) : super(key: key);
@override
State<AddProduct> createState() => _AddProductState();
}
class _AddProductState extends State<AddProduct> {
static const _stepIcons = [
Icons.add_circle,
Icons.document_scanner,
Icons.camera_alt_rounded,
Icons.check,
];
static const _titles = ['المنتج', 'تفاصيل', 'الصور', 'نشر'];
var _contnet = [
FirstStep(),
SecondStep(),
ThirdStep(),
Forth()];
var _curStep = 1;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('إضافة منتج'),
centerTitle: true,
),
persistentFooterButtons: [
Row(
children: [
Expanded(
child: ElevatedButton(
child: const Text('التالي'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(16),
),
onPressed: () => setState(() {
if (_curStep < _stepIcons.length) _curStep++;
}),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: ElevatedButton(
child: const Text('رجوع'),
style: ElevatedButton.styleFrom(
primary: Colors.white,
onPrimary: Colors.black,
padding: const EdgeInsets.all(16)),
onPressed: () => setState(() {
if (_curStep > 1) _curStep--;
}),
),
),
],
)
],
body: CustomeStepper(
icons: _stepIcons,
width: MediaQuery.of(context).size.width,
curStep: _curStep,
titles: _titles,
circleActiveColor: Colors.green,
circleInactiveColor: const Color(0xffD5D5D5),
iconActiveColor: Colors.white,
iconInactiveColor: Colors.white,
textActiveColor: Colors.green,
textInactiveColor: const Color(0xffD5D5D5),
content: _contnet,
),
);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我遇到了同样的问题,查看您的表单小部件会有所帮助。我将尽力描述您需要做什么。
表单中的文本字段应该与您的模型类相关联。示例:onChange: Product.title = TextField.value。并且您应该在模型属性中使用初始值,例如:initialValue: Product.title。我认为这样您可以保留表单中输入的状态。
至于问题的第二部分,控制步进器的主小部件应该有一个状态变量,例如 isCompleted,在最后一步中,将此变量设置为“true”,并且步进器的主体应该位于堆栈,在您的堆栈中检查是否“isCompleted”?步进器:SummaryWidget。
如何处理文本字段的阿拉伯标题并将其与类模型属性进行匹配?
希望我的回答可以帮助到您!
I had the same problem, It would help to see your forms widgets. I will try my best to describe what you need to do.
Your textfields in your forms should be tied to your model class. Example: onChange: Product.title = TextField.value. and you should use initial value with your model properties, example: initialValue: Product.title. I think this way you can retain the state of the inputs in your forms.
As for the second part of your question, the Main widget that is controlling the stepper should have a state variable, such as isCompleted, on the last step you set this variable to 'true' and the main body of the stepper should be in a stack, in your stack you check if "isCompleted" ? Stepper : SummaryWidget.
How are handling Arabic titles for text fields and matching them with your class model properties?
I hope my answer can help!