Flutter 将值传递给上一个小部件

Flutter 将值传递给上一个小部件,flutter,Flutter,我有一个简单的表格,里面有一个圆形的相机,当按下这个按钮时,可以选择从画廊或相机拍照。为了使我的小部件更紧凑,我将它分离到一些文件中 FormDoSensScreen(它是主屏幕) DosenImagePicker(它是唯一的循环雷达) ModalBottomSheet PickImage(用于显示ModalBottomSheet) 问题是,我不知道如何将值从ModalBottomSheetPickImage传递到FormDosenScreen。因为来自ModalBottomSheetPickI

我有一个简单的表格,里面有一个圆形的相机,当按下这个按钮时,可以选择从画廊或相机拍照。为了使我的小部件更紧凑,我将它分离到一些文件中

  • FormDoSensScreen(它是主屏幕)
  • DosenImagePicker(它是唯一的循环雷达)
  • ModalBottomSheet PickImage(用于显示ModalBottomSheet)
  • 问题是,我不知道如何将值从ModalBottomSheetPickImage传递到FormDosenScreen。因为来自ModalBottomSheetPickImage的值将用于插入操作

    我只成功地从第三个小部件传递到第二个小部件,但当我再次从第二个小部件传递到第一个小部件时,值为null,我认为问题是从第二个小部件传递到第一个小部件

    如何从第三个小部件传递到第一个小部件

    第一个小部件
    类FormDoSensScreen扩展StatefulWidget{
    静态常量routeName='/formdosen screen';
    @凌驾
    _FormDoSensCrenstate createState()=>\u FormDoSensCrenstate();
    }
    类_formDoSensCrenstate扩展状态{
    字符串选择文件;
    @凌驾
    小部件构建(构建上下文){
    final detectKeyboardOpen=MediaQuery.of(context).viewInsets.bottom;
    打印(“触发器”);
    返回脚手架(
    appBar:appBar(
    标题:对,
    标题:文本(“Tambah Dosen”),
    行动:[
    弹出菜单按钮(
    itemBuilder:(\u)=>[
    PopupMenuItem(
    child:Text('Tambah Pelajaran'),
    值:“添加_pelajaran”,
    ),
    ],
    onSelected:(字符串值){
    开关(值){
    “add_pelajaran”一案:
    Navigator.of(context.pushNamed)(FormPelajaranScreen.routeNamed);
    打破
    违约:
    }
    },
    )
    ],
    ),
    主体:堆栈(
    fit:StackFit.expand,
    儿童:[
    SingleChildScrollView(
    子:列(
    mainAxisSize:mainAxisSize.min,
    crossAxisAlignment:crossAxisAlignment.stretch,
    儿童:[
    尺寸箱(高度:20),
    DosenImagePicker(onPickedImage:(文件)=>selectedFile=file),
    尺寸箱(高度:20),
    卡片(
    边距:常量边集。对称(水平:15,垂直:10),
    孩子:填充(
    填充:常数边集。全部(20),
    子:列(
    crossAxisAlignment:crossAxisAlignment.stretch,
    儿童:[
    TextFormFieldCustom(
    onSaved:(值){},
    标签文字:“Nama Dosen”,
    ),
    尺寸箱(高度:20),
    TextFormFieldCustom(
    onSaved:(值){},
    前缀:图标(Icons.email),
    labelText:“电子邮件地址”,
    键盘类型:TextInputType.emailAddress,
    ),
    尺寸箱(高度:20),
    TextFormFieldCustom(
    onSaved:(值){},
    键盘类型:TextInputType.number,
    输入格式化程序:[
    //InputNumberFormat(),
    WhiteListingPutFormatter.digitsOnly
    ],
    前缀:图标(图标。本地电话),
    labelText:“Telepon Dosen”,
    ),
    ],
    ),
    ),
    ),
    SizedBox(高度:kToolbarHeight),
    ],
    ),
    ),
    定位(
    孩子:可见度(
    可见:detectKeyboardOpen>0?假:真,
    孩子:升起按钮(
    已按下:(){
    打印(所选文件);
    },
    MaterialTargetSize:MaterialTargetSize.shrinkWrap,
    颜色:colorPallete.primaryColor,
    子:文本(
    "辛潘",,
    样式:TextStyle(fontWeight:fontWeight.bold,fontFamily:AppConfig.headerFont),
    ),
    形状:圆形RectangleBorder(borderRadius:borderRadius.circular(20)),
    textTheme:buttonexttheme.primary,
    ),
    ),
    底部:KToolbar高度/2,
    左:尺寸。宽度(上下文)/15,
    右:尺寸。宽度(上下文)/15,
    )
    ],
    ),
    );
    }
    }
    
    第二个小部件
    
    类DosenImagePicker扩展StatefulWidget{
    最终函数(字符串文件)onPickedImage;
    DosenImagePicker({@required this.onPickedImage});
    @凌驾
    DosenImagePickerState createState()=>DosenImagePickerState();
    }
    类DosenImagePickerState扩展了状态{
    字符串选择图像;
    @凌驾
    小部件构建(构建上下文){
    返回对齐(
    对齐:对齐.center,
    孩子:InkWell(
    onTap:()异步{
    等待展示ModalBottomSheet(
    上下文:上下文,
    生成器:(上下文)=>ModalBottomSheetPickImage(
    onPickedImage:(文件){
    设置状态(){
    选择edimage=file;
    widget.onPickedImage(选择eImage);
    打印(“Hellooo dosen图像选择器$SelecteImage”);
    });
    },
    ),
    );
    },
    孩子:圆环星(
    前底色:colorPallete.black,
    backgroundImage:SelecteImage==null?null:MemoryImage(base64.decode(SelecteImage)),
    半径:尺寸。宽度(上下文)/6,
    美国银行
    
    class FormDosenScreen extends StatefulWidget {
      static const routeNamed = '/formdosen-screen';
    
      @override
      _FormDosenScreenState createState() => _FormDosenScreenState();
    }
    
    class _FormDosenScreenState extends State<FormDosenScreen> {
      String selectedFile;
      @override
      Widget build(BuildContext context) {
        final detectKeyboardOpen = MediaQuery.of(context).viewInsets.bottom;
        print('trigger');
        return Scaffold(
          appBar: AppBar(
            centerTitle: true,
            title: Text('Tambah Dosen'),
            actions: <Widget>[
              PopupMenuButton(
                itemBuilder: (_) => [
                  PopupMenuItem(
                    child: Text('Tambah Pelajaran'),
                    value: 'add_pelajaran',
                  ),
                ],
                onSelected: (String value) {
                  switch (value) {
                    case 'add_pelajaran':
                      Navigator.of(context).pushNamed(FormPelajaranScreen.routeNamed);
                      break;
                    default:
                  }
                },
              )
            ],
          ),
          body: Stack(
            fit: StackFit.expand,
            children: <Widget>[
              SingleChildScrollView(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    SizedBox(height: 20),
                    DosenImagePicker(onPickedImage: (file) => selectedFile = file),
                    SizedBox(height: 20),
                    Card(
                      margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
                      child: Padding(
                        padding: const EdgeInsets.all(20),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: <Widget>[
                            TextFormFieldCustom(
                              onSaved: (value) {},
                              labelText: 'Nama Dosen',
                            ),
                            SizedBox(height: 20),
                            TextFormFieldCustom(
                              onSaved: (value) {},
                              prefixIcon: Icon(Icons.email),
                              labelText: 'Email Dosen',
                              keyboardType: TextInputType.emailAddress,
                            ),
                            SizedBox(height: 20),
                            TextFormFieldCustom(
                              onSaved: (value) {},
                              keyboardType: TextInputType.number,
                              inputFormatter: [
                                // InputNumberFormat(),
                                WhitelistingTextInputFormatter.digitsOnly
                              ],
                              prefixIcon: Icon(Icons.local_phone),
                              labelText: 'Telepon Dosen',
                            ),
                          ],
                        ),
                      ),
                    ),
                    SizedBox(height: kToolbarHeight),
                  ],
                ),
              ),
              Positioned(
                child: Visibility(
                  visible: detectKeyboardOpen > 0 ? false : true,
                  child: RaisedButton(
                    onPressed: () {
                      print(selectedFile);
                    },
                    materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                    color: colorPallete.primaryColor,
                    child: Text(
                      'SIMPAN',
                      style: TextStyle(fontWeight: FontWeight.bold, fontFamily: AppConfig.headerFont),
                    ),
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
                    textTheme: ButtonTextTheme.primary,
                  ),
                ),
                bottom: kToolbarHeight / 2,
                left: sizes.width(context) / 15,
                right: sizes.width(context) / 15,
              )
            ],
          ),
        );
      }
    }
    
    
    class DosenImagePicker extends StatefulWidget {
      final Function(String file) onPickedImage;
      DosenImagePicker({@required this.onPickedImage});
      @override
      DosenImagePickerState createState() => DosenImagePickerState();
    }
    
    class DosenImagePickerState extends State<DosenImagePicker> {
      String selectedImage;
      @override
      Widget build(BuildContext context) {
        return Align(
          alignment: Alignment.center,
          child: InkWell(
            onTap: () async {
              await showModalBottomSheet(
                context: context,
                builder: (context) => ModalBottomSheetPickImage(
                  onPickedImage: (file) {
                    setState(() {
                      selectedImage = file;
                      widget.onPickedImage(selectedImage);
                      print('Hellooo dosen image picker $selectedImage');
                    });
                  },
                ),
              );
            },
            child: CircleAvatar(
              foregroundColor: colorPallete.black,
              backgroundImage: selectedImage == null ? null : MemoryImage(base64.decode(selectedImage)),
              radius: sizes.width(context) / 6,
              backgroundColor: colorPallete.accentColor,
              child: selectedImage == null ? Text('Pilih Gambar') : SizedBox(),
            ),
          ),
        );
      }
    }
    
    
    
    class ModalBottomSheetPickImage extends StatelessWidget {
      final Function(String file) onPickedImage;
    
      ModalBottomSheetPickImage({@required this.onPickedImage});
    
      @override
      Widget build(BuildContext context) {
        return SizedBox(
          child: Padding(
            padding: const EdgeInsets.all(15.0),
            child: Wrap(
              alignment: WrapAlignment.spaceEvenly,
              children: <Widget>[
                InkWell(
                  onTap: () async {
                    final String resultBase64 =
                        await commonFunction.pickImage(quality: 80, returnFile: ReturnFile.BASE64);
                    onPickedImage(resultBase64);
                  },
                  child: CircleAvatar(
                    foregroundColor: colorPallete.white,
                    backgroundColor: colorPallete.green,
                    child: Icon(Icons.camera_alt),
                  ),
                ),
                InkWell(
                  onTap: () async {
                    final String resultBase64 =
                        await commonFunction.pickImage(returnFile: ReturnFile.BASE64, isCamera: false);
                    onPickedImage(resultBase64);
                  },
                  child: CircleAvatar(
                    foregroundColor: colorPallete.white,
                    backgroundColor: colorPallete.blue,
                    child: Icon(Icons.photo_library),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    
    class ImageModel extends ChangeNotifier {
      String _base64Image;
      get base64Image => _base64Image;
      set base64Image(String base64Image) {
        _base64Image = base64Image;
        notifyListeners();
      }
    }
    
    final model=Provider.of<ImageModel>(context,listen:false);
    String image=model.base64Image; //get data
    model.base64Image=resultBase64; //set your image data after you used ImagePicker
    
    @override
    Widget build(BuildContext context) {
     //other widgets
     Selector<ImageModel, String>(
      selector: (_, model) => model.base64Image,
      builder: (_, image, __) {
       return Text(image);
         },
       );
      }
     )
    }