将值传递给上一个小部件

泽弗里·雷南多

我有一个简单的表格,里面有 CircularAvatar,当按下这个时显示 ModalBottomSheet 可以在从画廊或相机拍照之间进行选择。为了使我的小部件更紧凑,我将它分成了一些文件。

  1. FormDosenScreen(它的主屏幕)
  2. DosenImagePicker(它只是 CircularAvatar)
  3. ModalBottomSheetPickImage(显示ModalBottomSheet)

问题是,我不知道如何将值从ModalBottomSheetPickImage传递FormDosenScreen因为来自ModalBottomSheetPickImage 的值,我将用于插入操作。

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

我如何从第三个 Widget 传递到第一个 Widget?

第一个小工具

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),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

大学

最干净、最简单的方法是通过 Provider。它是一种状态管理解决方案,可用于在应用程序周围传递值以及仅重建更改的小部件。(例如:当 Text 小部件的值发生变化时)。以下是在您的场景中使用 Provider 的方法:

这是您的模型的外观:

class ImageModel extends ChangeNotifier {
  String _base64Image;
  get base64Image => _base64Image;
  set base64Image(String base64Image) {
    _base64Image = base64Image;
    notifyListeners();
  }
}

不要忘记添加 getter 和 setter,这样如果您有任何依赖它的 ui,您就可以使用 notifyListeners()。

以下是在 UI 中访问 ImageModel 值的方法:

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

以下是在文本小部件中显示数据的方法(理想情况下,您应该使用 Selector 而不是 Consumer 以便小部件仅在其侦听的值发生变化时重建):

@override
Widget build(BuildContext context) {
 //other widgets
 Selector<ImageModel, String>(
  selector: (_, model) => model.base64Image,
  builder: (_, image, __) {
   return Text(image);
     },
   );
  }
 )
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将一个小部件的值(年龄)传递给另一个小部件

tkinter-将条目小部件值传递给另一个类

如何将单个小部件的值传递给Panel / Bokeh中一个对象的多个实例

如何将小部件构造函数作为参数传递给另一个小部件来构建

如何将数据传递给另一个小部件内的小部件

将Cupertino Datepicker传递给另一个小部件

将值传递给NavigationViewController堆栈中的上一个View Controller

如何将值传递给上一个ViewContoller

如何将数据从一个小部件传递到其同级小部件?

Flutter 通过 Navigation.push 将 TextField 输入传递给另一个小部件

将数据从一个小部件传递到另一个小部件

Flutter小部件不返回值并关注下一个/上一个元素

如何将上下文传递给另一个小部件?

在 Flutter 中如何将值传递给小部件

Flutter如何使Wrap小部件中的Text小部件从上一个小部件的末尾开始而不是在前一个小部件的下面开始?

如何在 tkinter 按钮小部件中获取 text 参数的值,然后将该值作为参数传递给同一个按钮?

气流:将执行日期前的上一个星期二传递给BashOperator

RXJava 将一个值传递给 onComplete

将值传递给下一个viewController

将数据传递给上一个活动并使用相同的按钮移至下一个活动

将ID从一个页面小部件传递到另一个页面方法

如何将变量作为参数传递给小部件二,在那里修改它,并将修改后的值返回给小部件一,Flutter

PyQt5使动态窗口小部件可单击并将参数传递给另一个函数

如何在另一个小部件的children属性中传递小部件列表?

将一个会话值传递给另一个会话值

将 String 值从一个有状态小部件更改为另一个有状态小部件

Flutter 获取一个小部件类变量的值

如何将值从SearchBar传递到Flutter中的上一个屏幕

创建一个将显示很长段落的小部件