0
votes

Simple Add Place widget

  • Title Text Field
  • Container - Render image from camera
  • Button - Activates camera device

I thought having a controller connected to TextField would automatically save the state of the input value. However, from my example, if I input the text without click "done" and immediately click on "Take Picture" button. The TextField input value is cleared after coming back from camera operation.

How to Reproduce Problem:

  1. Input text into the field
  2. Immediately click on the Camera button without click done / check or hit enter on the keyboard
  3. Take a picture confirm.
  4. Come back to page the TextField is empty

Example Code:

AddPlacePage StatefulWidget

Column(
              children: <Widget>[
                TextField(
                  decoration: InputDecoration(labelText: 'Title'),
                  controller: _titleController,
                ),

                ImageInput(),
              ],
            ),

ImageInput StatefulWidget

  class _ImageInputState extends State<ImageInput> {
  File _storedImage;

  Future<void> _takePicture() async {
    final imageFile = await ImagePicker.pickImage(
      source: ImageSource.camera,
      maxWidth: 600,
    );
    setState(() {
      _storedImage = imageFile;
    });
    ...
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Container(
          ...
          child: _storedImage != null
              ? Image.file(
                  _storedImage,
                  fit: BoxFit.cover,
                  width: double.infinity,
                )
              : Text(
                  'No Image Taken',
                  textAlign: TextAlign.center,
                ),
          alignment: Alignment.center,
        ),

        Expanded(
          child: FlatButton.icon(
            icon: Icon(Icons.camera),
            label: Text('Take Picture'),
            textColor: Theme.of(context).primaryColor,
            onPressed: () => _takePicture(),
          ),
        ),
      ],
    );
  }
}

Question:

How can I modify TextField's controller to retain input value even after exiting the application to access device camera?

TextField(
  decoration: InputDecoration(labelText: 'Title'),
  controller: _titleController,
),

I did try to create a local variable and try to use onChange:

   String _inputValue

   build(BuildContext context){

     ...   
     TextField(
        decoration: InputDecoration(labelText: 'Title'),
        controller: _titleController,
        onChange: (value) => _inputValue = value;
     ),          

However the effect is the same once returning from the camera as Flutter re-reders the page, both _inputValue and _titleController.text is cleared.

Example code: https://github.com/erich5168/flutter_camera_example

1
declare a static variable in your class, then assign the text field value to it using on text changed method.OMi Shah
This should not happen, the text should remain on the text field. Your TextField is on a different view than the button that triggers the camera?João Soares
@OMiShah I did... see code below question I used an onChnage... but did not workEric Huang
@JoãoSoares Yes you are right... AddPlacePage has a scaffold [ this is where the TextField resides ]. And have extracted the Camera button and the image preview to a separate StatefulWidget.Eric Huang
@JoãoSoares I have added github repo... hope this makes it easier... thank youEric Huang

1 Answers

0
votes

You can use share preferences to save the String to device then call it when you back to text field. This is how I implement:

class LocalStorage {
  static SharedPreferences instance;

  static Future init() async {
    instance = await SharedPreferences.getInstance();
  }

  static dynamic getValue(String key, dynamic emptyValue) {
    if (LocalStorage.instance.containsKey(key)) {
      return LocalStorage.instance.get(key);
    }
    return emptyValue;
  }
}

set it to text field:

TextEditingController _usernameController =
  new TextEditingController(text: LocalStorage.getValue('UserName', ''));