Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forms 颤振如何使用tabview表单_Forms_Flutter_Tabview - Fatal编程技术网

Forms 颤振如何使用tabview表单

Forms 颤振如何使用tabview表单,forms,flutter,tabview,Forms,Flutter,Tabview,我正在尝试创建一个具有多个选项卡的表单,但由于某些原因,如果我在表单上调用validate或save,我只能从处于活动状态的选项卡中获取值,对于错误也是如此。我认为这可能是因为表单只从当前在屏幕上呈现的字段中获取值 所以,有人能告诉我如何使表单与多个选项卡视图一起工作,以便在更改选项卡后,我可以验证尚未访问的选项卡以及已授予的选项卡 有AutomaticEpaLiveClientMixin,但它只能使状态保持活动状态,但我更感兴趣的是onSave或validator,因为我是在父元素而不是在选项

我正在尝试创建一个具有多个选项卡的表单,但由于某些原因,如果我在表单上调用validate或save,我只能从处于活动状态的选项卡中获取值,对于错误也是如此。我认为这可能是因为表单只从当前在屏幕上呈现的字段中获取值

所以,有人能告诉我如何使表单与多个选项卡视图一起工作,以便在更改选项卡后,我可以验证尚未访问的选项卡以及已授予的选项卡

有AutomaticEpaLiveClientMixin,但它只能使状态保持活动状态,但我更感兴趣的是onSave或validator,因为我是在父元素而不是在选项卡视图中管理状态


提前感谢

我与您有相同的需求,我正试图使用一个提供程序来管理不同的表单,该提供程序具有
列表formKeys=[GlobalKey(),GlobalKey()…]每个表单的键。然后在选项卡栏上的一个按钮中按下:form.validate(formKey)用于每个表单。如果所有表单都正常,请保存信息,否则将显示错误消息。

我与您有相同的需求,我正在尝试使用具有
列表formKeys=[GlobalKey(),GlobalKey()…]的提供程序来管理不同的表单每个表单的键。然后在选项卡栏上的一个按钮中按下:form.validate(formKey)用于每个表单。如果所有表单都正常,请保存信息,否则会显示错误消息。

现在我使用的是页面视图和选项卡视图的混合,而不是默认的颤振页面视图。我正在使用此软件包(正如在Flatter默认页面视图中一样,没有预加载选项,但一旦加载页面,我们就可以告诉Flatter保存它,因此此包实际上提供了一个关于应预加载多少页面的选项等。)

然后使用Tabbar切换页面,如下所示

class IssuesEditScreen extends StatefulWidget {
   static final routeName = "/issues_edit";

   @override
   _IssuesEditScreenState createState() => _IssuesEditScreenState();
}

class _IssuesEditScreenState extends State<IssuesEditScreen>
with SingleTickerProviderStateMixin {
   final GlobalKey<FormState> _form = GlobalKey();
   final _scaffold = GlobalKey<ScaffoldState>();

   Issue _instance;
   TabController _tabController;
   PreloadPageController _pageController = PreloadPageController(
       initialPage: 0, keepPage: true, viewportFraction: 0.99);
   bool _canChange = true;
   bool _loading = false;
   Map<String, String> _errors = {};
   Map<String, dynamic> _formData = {};


@override
void dispose() {
   super.dispose();
   _tabController.dispose();
   _pageController.dispose();
}

@override
void initState() {
   // TODO: implement initState
   _tabController = TabController(length: 3, vsync: this);
   _tabController.addListener(() {
   if (_tabController.indexIsChanging) {
       changePage(_tabController.index, page: true);
   }
   });
   super.initState();
}

void _submit() {
   if (!_form.currentState.validate()) {
      _scaffold.currentState
       .showSnackBar(SnackBar(content: Text("Please resolve given errors")));
      return;
   }
   _formData.clear();
   _form.currentState.save();
}
void changePage(index, {page = false, tab = false}) async {
   if (page) {
     _canChange = false;
     await _pageController.animateToPage(index,
       duration: Duration(milliseconds: 500), curve: Curves.ease);
     _canChange = true;
   } else {
     _tabController.animateTo(index);
   }
}

@override
Widget build(BuildContext context) {
 return Scaffold(
   key: _scaffold,
   appBar: AppBar(
     title: Text("Form"),
     bottom: TabBar(
       controller: _tabController,
       tabs: [
         Tab(
           text: "Page1",
         ),
         Tab(
           text: "Page2",
         ),
         Tab(text: "Page3"),
       ],
     ),
     actions: [
       FlatButton(
        child: Text("Save"), 
        onPressed: __submit)
      
      ],
    ),
   body: Form(
     key: _form,
     child: PreloadPageView(
      preloadPagesCount: 5,
      physics: AlwaysScrollableScrollPhysics(),
      controller: _pageController,
      onPageChanged: (index) {
        if (_canChange) {
          changePage(index);
        }
      },
      children: [
        Page1(formData: _formData, errors: _errors,),
        Page2(formData: _formData, errors: _errors),
        Page3(formData: _formData, errors: _errors)
      ],
    ),
  ),
  );
 }
}

class Page1 extends StatelessWidget {
  const Page1 ({
    Key key,
    @required Map<String,dynamic > formData,
    @required Map<String, String> errors,
  }) : _formData = formData, _errors = errors, super(key: key);

 final Map<String,dynamic > _formData;
 final Map<String, String> _errors;

 @override
 Widget build(BuildContext context) {
   return Padding(
    padding: const EdgeInsets.all(8.0),
    child: Card(
        elevation: 3,
        child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Container(
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    TextFormField(
                      onSaved: (value) =>
                      _formData['field1'] = value,
                      decoration: BorderInputDecorator(
                        errorText: _errors['field1'],
                        label: "Field1",
                      ),
                    validator: (value) {
                      if (value.isEmpty) {
                        return "This Field is required";
                       }
                      return null;
                     },
                    ),
                  ],
                ),
              ),
            )
           )
          )
       );
  }
}
class IssuseEdit屏幕扩展StatefulWidget{
静态最终路由名称=“/issues\u edit”;
@凌驾
_IssuesEditScreenState createState()=>_IssuesEditScreenState();
}
类_IssuesEditScreenState扩展状态
使用SingleTickerProviderStateMixin{
最终的GlobalKey _form=GlobalKey();
最终_scaffold=GlobalKey();
问题(例如),;
TabController\u TabController;
Preload pageController\u pageController=Preload pageController(
initialPage:0,keepPage:true,viewportFraction:0.99);
bool_canChange=true;
bool\u加载=假;
Map_errors={};
映射_formData={};
@凌驾
无效处置(){
super.dispose();
_tabController.dispose();
_pageController.dispose();
}
@凌驾
void initState(){
//TODO:实现initState
_tabController=tabController(长度:3,vsync:this);
_tabController.addListener((){
if(tab controller.indexIsChanging){
changePage(\u tabController.index,page:true);
}
});
super.initState();
}
作废(提交){
if(!\u form.currentState.validate()){
_当前状态
.showSnackBar(SnackBar(内容:文本(“请解决给定错误”));
返回;
}
_formData.clear();
_form.currentState.save();
}
void changePage(索引,{page=false,tab=false})异步{
若有(第页){
_canChange=假;
等待pageController.animateToPage(索引,
持续时间:持续时间(毫秒:500),曲线:Curves.ease);
_canChange=true;
}否则{
_tabController.animateTo(索引);
}
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
关键词:_脚手架,
appBar:appBar(
标题:文本(“表格”),
底部:选项卡栏(
控制器:\ tab控制器,
选项卡:[
标签(
正文:“第1页”,
),
标签(
正文:“第2页”,
),
选项卡(文本:“第3页”),
],
),
行动:[
扁平按钮(
子项:文本(“保存”),
按下按钮:\ u提交)
],
),
正文:表格(
键:_形式,
子:页面视图(
地址:5,
物理:AlwaysScrollableScrollPhysics(),
控制器:_pageController,
onPageChanged:(索引){
如果(_canChange){
更改页面(索引);
}
},
儿童:[
第1页(formData:_formData,错误:_errors,),
第2页(formData:_formData,错误:_errors),
第3页(formData:\u formData,错误:\u errors)
],
),
),
);
}
}
类Page1扩展了无状态小部件{
常数第1页({
关键点,
@所需的地图格式数据,
@必需的映射错误,
}):_formData=formData,_errors=errors,super(key:key);
最终地图(表格数据);;
最终地图错误;
@凌驾
小部件构建(构建上下文){
返回填充(
填充:常数边集全部(8.0),
孩子:卡片(
标高:3,
孩子:填充(
填充:常数边集全部(8.0),
子:容器(
子:SingleChildScrollView(
子:列(
儿童:[
TextFormField(
onSaved:(值)=>
_formData['field1']=值,
装饰:BorderInputDecorator(
errorText:_errors['field1'],
标签:“字段1”,
),
验证器:(值){
if(value.isEmpty){
返回“此字段为必填字段”;
}
返回null;
},
),
],
),
),
)
)
)
);
}
}
正如您所看到的,您可以使用onsave验证器并添加更多页面,只需在表单上保存或验证即可获得提交中的所有数据


可能存在语法问题

目前,我使用的是页面视图和选项卡视图的混合,而不是默认的Flatter页面视图。我正在使用此软件包(正如在Flatter默认页面视图中一样,没有预加载选项,但一旦加载页面,我们可以告诉Flatter保存它,因此此软件包实际上在