为什么选择的值没有反映在 showModalBottomSheet 中?

Why is selected value not reflecting in showModalBottomSheet with flutter?

首先,我创建了一个设计好的底部sheet,其中有两个列表显示数字(左侧)和选项(小时、天、周、月),借助于CupertinoPicker 小部件,

数字将取决于我select的选择,如果我select小时,左边的数字应该是1-24,如果我select周,数字应该是 1-4,我 select 天,数字应该是 1-30,最后我 select 月份数字应该是 1-12。

代码:

所有列表变量:

List<String> reminderDay = ['hour','day','week','month'];
  List<String> reminderHoursVal =['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24'];
  List<String> reminderDaysVal =['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31'];
  List<String> reminderMonthsVal =['1','2','3','4','5','6','7','8','9','10','11','12'];
  List<String> reminderWeeksVal =['1','2','3','4'];
  String selectedReminderVal='1';
  String selectedReminderDay ='hour';

底部代码sheet:

addReminder(){ 
   
    showModalBottomSheet(
      
      context: context,
      builder: (BuildContext context) {
        return AnimatedPadding(
          padding: MediaQuery.of(context).viewInsets,
          duration: const Duration(milliseconds: 100),
          curve: Curves.decelerate,
          child: Container(
            padding: const EdgeInsets.only(top:8,right: 8, left:8,bottom: 8),
            height: MediaQuery.of(context).size.height/2,
            // color: Colors.transparent,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(30),
                topRight: Radius.circular(30)
              )
            ),
            child: Container(
              child: Column(
                // mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  SizedBox(height:10),
                   Text("Set a reminder",
                   style: TextStyle(
                     fontSize:18,
                     fontWeight:FontWeight.bold,
                     color: Colors.grey
                   ),
                   ),
                   SizedBox(height:20),
                  Container(
                    margin: const EdgeInsets.only(left: 10, right: 10),
                  
                     height: MediaQuery.of(context).size.height/4,
                      decoration: BoxDecoration(
                         color: Colors.grey[100],
                        borderRadius: BorderRadius.circular(10)
                      ),
                    child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                    Expanded(
                      
                      child: CupertinoPicker(
                          scrollController: new FixedExtentScrollController(
                            initialItem: 0,
                          ),
                          itemExtent: 30,
                          backgroundColor: Colors.grey[100],
                          onSelectedItemChanged: (int val) {
                           setState(() {
                             if(selectedReminderDay=='day'){
                               selectedReminderVal = reminderDaysVal[val];
                             }else if(selectedReminderDay=='week'){
                                selectedReminderVal = reminderWeeksVal[val];
                             }else if(selectedReminderDay=='month'){
                                selectedReminderVal = reminderMonthsVal[val];
                             }else{
                               selectedReminderVal = reminderHoursVal[val];
                             }
                              
                            print("selectedReminderVal:$selectedReminderVal");
                           });

                          },
                          children:selectedReminderDay=='day'?reminderDaysVal
                          :selectedReminderDay=='week'?reminderWeeksVal
                            :selectedReminderDay=='month'?reminderMonthsVal:reminderHoursVal// ['hour','day','week','month']; reminderHoursVal
                              .map(
                                (item) => Center(
                                  child: Text(
                                    item,
                                    style: TextStyle(
                                      fontSize: 16,
                                      // fontWeight:FontWeight.bold,
                                    ),
                                  ),
                                ),
                              )
                              .toList()),
                    ),
                    Expanded(
                      child: CupertinoPicker(
                        
                          scrollController: new FixedExtentScrollController(
                            initialItem: 0,
                          ),
                          itemExtent: 30,
                          backgroundColor: Colors.grey[100],
                          onSelectedItemChanged: (int val) {
                              setState(() {
                                selectedReminderDay = reminderDay[val];
                                print("selectedReminderDay:$selectedReminderDay");
                              });
                          },
                          children: reminderDay
                              .map(
                                (item) => Center(
                                  child: Text(
                                    item,
                                    style: TextStyle(
                                      fontSize: 16,
                                      // fontWeight:FontWeight.bold,
                                    ),
                                  ),
                                ),
                              )
                              .toList()),
                    ),
                  ])
                  ),
                  SizedBox(height:15),
                  // selectedVal!=null?Text(selectedVal.toString()):Container()
                  Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text("You'll get the reminder"),
                      Text('$selectedReminderVal $selectedReminderDay before the event')
                    ],
                  ),
                 SizedBox(height:25),
                 Padding(
                   padding: const EdgeInsets.only(left: 10, right: 10),
                    child: Row(
                     mainAxisAlignment: MainAxisAlignment.spaceBetween,
                     children: [
                       InkWell(
                         onTap: (){
                           Navigator.pop(context);
                         },
                         child: Text("Cancel",
                          style: TextStyle(
                            fontSize: 18,
                            color: Colors.blue,
                            fontWeight: FontWeight.bold
                          ),
                         ),
                       ),
                       InkWell(
                         onTap: (){
                          
                            Navigator.pop(context);
                         },
                         child: Container(
                            alignment: Alignment.center,
                            decoration: BoxDecoration(
                              color: Colors.blue,
                              borderRadius: BorderRadius.circular(8)
                            ),
                            width: MediaQuery.of(context).size.width/5,
                            height: MediaQuery.of(context).size.height/25 ,
                            child: Text("Save", style:TextStyle(
                              color: Colors.white,
                              fontSize: 19
                            )),
                          ),
                       )
                     ],
                   ),
                 )
                ],
              ),
            )  
          ),
        );
      }, 
      
    );
  }

截图:

这是因为你设置的状态和模态底部的状态不一样sheet。

现在,当您调用 setState 时,您实际上是在重建模态底部下的有状态小部件 sheet。

要解决此问题,只需将底部 sheet 包裹在有状态生成器中。

StatefulBuilder(
            builder: (context, setState) {
              return AnimatedPadding(
              padding: MediaQuery.of(context).viewInsets,
              duration: const Duration(milliseconds: 100),
              curve: Curves.decelerate,
              child: Container(
                padding: const EdgeInsets.only(top:8,right: 8, left:8,bottom: 8),
                height: MediaQuery.of(context).size.height/2,
                // color: Colors.transparent,
                decoration: BoxDecoration(
                  color: Colors.white,

....

当我们在现有状态下创建新的上下文小部件时,状态会变得不同,bottomSheets 类似于具有新上下文的对话框,构建器会从父状态构建一个全新的小部件,以创建自己的有状态状态用有状态的构建器和用户自己的 setState 来更改此上下文中的任何内容而不是父级的 例如:

StatefulBuilder(
 builder: (context, setStateChild) {
            return AnimatedPadding(...
                    Expanded(
                  child: CupertinoPicker(
                    
                      scrollController: new FixedExtentScrollController(
                        initialItem: 0,
                      ),
                      itemExtent: 30,
                      backgroundColor: Colors.grey[100],
                      onSelectedItemChanged: (int val) {
                          setStateChild(() {
                            selectedReminderDay = reminderDay[val];
                            print("selectedReminderDay:$selectedReminderDay");
                          });
                      },);
                 child: ... ),

}