पिछले विजेट के लिए पासिंग वैल्यू

Aug 16 2020

मेरे पास सरल रूप है, इसके अंदर वृत्ताकारअवतार है जब यह गैलरी या कैमरे से तस्वीर लेने के बीच चुनने के लिए ModalBottomSheet दबाया जाता है। मेरे विजेट को अधिक कॉम्पैक्ट बनाने के लिए, मैंने इसे कुछ फ़ाइल में अलग कर दिया।

  1. फॉर्मडेनस्क्रीन (यह मुख्य स्क्रीन है)
  2. DosenImagePicker (यह केवल परिपत्र है)
  3. ModalBottomSheetPickImage (यह ModalBottomSheet दिखाने के लिए)

समस्या यह है, मैं नहीं जानता कि कैसे ModalBottomSheetPickImage से FormDosenScreen को मान दिया जाए । क्योंकि ModalBottomSheetPickImage से मूल्य मैं ऑपरेशन सम्मिलित करने के लिए उपयोग करूंगा।

मैं केवल तीसरी विजेट से दूसरी विजेट से गुजरने में सफलता प्राप्त करता हूं, लेकिन जब मैं दूसरी विजेट से पहली विजेट पर फिर से गुजरता हूं तो मान शून्य होता है, और मुझे लगता है कि समस्या दूसरी विजेट से पहली विजेट में गुजर रही है।

मैं तीसरी विजेट से पहली विजेट में कैसे गुजर सकता हूं?

पहला विजेट

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

जवाब

2 Uni Aug 17 2020 at 04:30

प्रदाता के माध्यम से ऐसा करने का सबसे साफ और आसान तरीका है। यह राज्य प्रबंधन समाधानों में से एक है जिसका उपयोग आप ऐप के चारों ओर मानों को पारित करने के लिए कर सकते हैं और साथ ही केवल विगेट्स को बदल सकते हैं। (पूर्व: जब पाठ विजेट का मूल्य बदलता है)। यहां बताया गया है कि आप अपने परिदृश्य में प्रदाता का उपयोग कैसे कर सकते हैं:

यह है कि आपका मॉडल कैसा दिखना चाहिए:

class ImageModel extends ChangeNotifier {
  String _base64Image;
  get base64Image => _base64Image;
  set base64Image(String base64Image) {
    _base64Image = base64Image;
    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

यहां बताया गया है कि आप अपने डेटा को टेक्स्ट विजेट में कैसे प्रदर्शित कर सकते हैं (आदर्श रूप में, आपको उपभोक्ता के बजाय चयनकर्ता का उपयोग करना चाहिए, ताकि विजेट केवल तब ही पुनर्निर्मित हो जाए जब मूल्य उसके परिवर्तनों को सुनता है):

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

आप इसे आसानी से हासिल कर सकते हैं। यदि आप Blocs का उपयोग कर रहे हैं।