ImagePicker with Bloc - Flutter

Viewed 314

How to add a stream with a picture(ImagePicker) in the bloc architecture, which can be selected from the phone, what should the widget look like?

My example is without validation whether it is to be included?

How should I work in a bloc along with the avatar photo?

I do not know how to approach it and what steps would be taken when it comes to both validation of such a photo, if possible, and the use of stream with bloc, any help is very welcome.

 class ProfileView extends StatefulWidget {
    const ProfileView({Key? key}) : super(key: key);

  @override
  _ProfileViewState createState() => _ProfileViewState();

  static Route route() {
  return MaterialPageRoute<void>(builder: (_) => ProfileView());
   }
 }

 class _ProfileViewState extends State<ProfileView> {


 final bloc = Bloc();


 @override
  Widget build(BuildContext context) {
  return Scaffold(
  body: _profilePage(context),
  );
 }

Widget _profilePage(BuildContext context) {
return ColorfulSafeArea(
  color: orange,
  child: Center(
    child: Column(
      children: [
        _changeAvatarButton(context),
        SizedBox(height: 15),
        _usernameTile(),
        SizedBox(height: 5),
        _cityTile(),
        SizedBox(height: 60),
      ],
    ),
  ),
);
// });
}

    // Profile avatar
       Widget _avatar() {
   return CircleAvatar(
    radius: 83,
   backgroundColor: orange,
   child: CircleAvatar(
    backgroundColor: Colors.white,
    radius: 80,
    child: Icon(personIcon, size: 60, color: orange),
  ),
  );
 }

Widget _changeAvatarButton(BuildContext context) {
return Column(
  children: [
    CircleAvatar(
      radius: 83,
      backgroundColor: orange,
      child: _image == null
          ? _avatar()
          : ClipRRect(
          borderRadius: BorderRadius.circular(83),
          child: Image.file(
            _image!,
            height: 160,
            // Change the size up or down accordingly border radius
            width: 160,
            // Change the size up or down accordingly border radius
            fit: BoxFit.cover,
          )),
       ),
        CustomButtonText(
        onPressed: () {
          _showPicker(context);
        },
        title: changePhoto,
        textColor: teal),
      ],
    );
    }

     File? _image;
    final picker = ImagePicker();

      Future getImage() async {
     final pickedFile = await picker.getImage(
      source: ImageSource.gallery, maxWidth: 1800, maxHeight: 1800);

    setState(() {
     if (pickedFile != null) {
      _image = File(pickedFile.path);
      } else {
       print(getImageText);
      }
       });
         }

   Future getCameraImage() async {
     final pickedFile = await picker.getImage(
      source: ImageSource.camera,
       maxWidth: 1800,
       maxHeight: 1800,
       );

        setState(() {
        if (pickedFile != null) {
         _image = File(pickedFile.path);
         } else {
         print(getImageText);
         }
       });
          }

     void _showPicker(BuildContext context) {
        showModalBottomSheet<void>(
    context: context,
    builder: (BuildContext bc) {
      return SafeArea(
        child: Container(
          child: Wrap(
            children: <Widget>[
              ListTile(
                  leading: Icon(photoIcon),
                  title: Text(showPickerPhoto),
                  onTap: () async {
                    await getImage();
                    Navigator.of(context).pop();
                  }),
              ListTile(
                leading: Icon(cameraIcon),
                title: Text(showPickerCamera),
                onTap: () async {
                  await getCameraImage();
                  Navigator.of(context).pop();
                },
              ),
            ],
          ),
        ),
      );
    });
  }

  Widget _usernameTile() {
 return StreamBuilder(
    stream: bloc.name,
    builder: (context, snapshot) {
      return CustomTextField(
          title: 'Name',
          obscureText: false,
          colour: Colors.black,
          keyboardType: TextInputType.name,
          labelText: labelTextUsername,
          onChanged: bloc.changeName,
          errorText: snapshot.error != null ? 'invalid name' : null
        // onChanged: (newValue) {
        //   bloc.changeName(newValue);
        // },
      );
    });
   }

  Widget _cityTile() {
    return StreamBuilder(
    stream: bloc.city,
    builder: (context, snapshot) {
      return CustomTextField(
        title: 'City',
        obscureText: false,
        colour: Colors.black,
        keyboardType: TextInputType.name,
        labelText: labelTextCity,
        onChanged: bloc.changeCity,
          errorText: snapshot.error != null ? 'invalid city' : null
          );
           });}

               }

Validators looks in this way:

  class Validators {
    static final RegExp _nameRegExp = RegExp(
     r'^(?=.*[a-z])[A-Za-z ]{3,}$',
      );
      final validateName =
      StreamTransformer<String, String>.fromHandlers(handleData: (name, sink) {
        if (name.contains(_nameRegExp)) {
        sink.add(name);
        } else {
         sink.addError('Enter a valid name');
        }
          });
          static final RegExp _cityRegExp = RegExp(
             r'^[a-zA-Z]+(?:[\s-][a-zA-Z]+)*$',
            );

     final validateCity =
      StreamTransformer<String, String>.fromHandlers(handleData: (city, sink) {
      if (city.contains(_cityRegExp)) {
         sink.add(city);
        } else {
         sink.addError('Enter a valid city');
            }
          });
    static final RegExp _avatarRegExp = RegExp(
       r'/.*\.(gif|jpe?g|bmp|png)$/igm',
        );

      final validateAvatar =
    StreamTransformer<String, String>.fromHandlers(handleData: (avatar, sink) {
      if (avatar.contains(_avatarRegExp)) {
         sink.add(avatar);
         } else {
         sink.addError('Enter a valid avatar photo');
          }
            });
             }

and Bloc:

    import 'dart:async';
   import 'dart:io';

  import 'validators.dart';

  class Bloc extends Validators {
  //instances
  //
   final _avatarPath = StreamController<File>();
   final _name = StreamController<String>();
   final _city = StreamController<String>();

 //add data stream
   Stream<File> get avatarPath => _avatarPath.stream;

  Stream<String> get name => _name.stream.transform(validateName);

   Stream<String> get city => _city.stream.transform(validateCity);

   // change data
    Function(File) get changeAvatarPath => _avatarPath.sink.add;

    Function(String) get changeName => _name.sink.add;

    Function(String) get changeCity => _city.sink.add;

   //for cleanup
   void  dispose() {
    _avatarPath.close();
     _name.close();
     _city.close();
 }
     }
  // bloc.changeName---> bloc.nameController.sin.add
    final bloc = new Bloc();
0 Answers
Related