Flutter: Can't refresh image picked on SliverAppBarDelegate

Issue

I am new on flutter, i am use the code below to pick and crop image, the app is successfully working, I can pick and crop the image from gallery or camera but the image don’t refresh until click hot reload button in vscode.

This is the code:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_cropper/image_cropper.dart';
import 'dart:math' as math;

class AddPhoto extends StatefulWidget {
  @override
  _AddPhotoState createState() => _AddPhotoState();
}

class _AddPhotoState extends State<AddPhoto> {
  File _image;
  final picker = ImagePicker();

  @override
  Widget build(BuildContext context) {
    return SliverPersistentHeader(
      pinned: true,
      floating: true,
      delegate: _SliverAppBarDelegate(
        _image,
        minHeight: 80.0,
        maxHeight: 200.0,
        onPressed: () => displayBottomSheet(context),
      ),
    );
  }

  void displayBottomSheet(BuildContext context) {
    showModalBottomSheet(
        context: context,
        builder: (ctx) {
          return SafeArea(
            child: Container(
              child: Wrap(
                children: <Widget>[
                  ListTile(
                    leading: Icon(Icons.camera_alt_outlined),
                    title: Text('Camera'),
                    onTap: () {
                      _obtenerImagen(ImageSource.camera);
                    },
                  ),
                  Divider(
                    height: 1,
                    thickness: 0.5,
                  ),
                  ListTile(
                    leading: Icon(Icons.photo_album_outlined),
                    title: Text('Gallery'),
                    onTap: () {
                      _getImage(ImageSource.gallery);
                    },
                  ),
                ],
              ),
            ),
          );
        });
  }


  _getImage(ImageSource source) async {
    final pickedImage = await picker.getImage(source: source);

    if (pickedImage != null) {
      File croppedImage = await ImageCropper.cropImage(
          sourcePath: pickedImage.path,
          aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1),
          compressQuality: 100,
          maxWidth: 240,
          maxHeight: 240,
          compressFormat: ImageCompressFormat.jpg,
          androidUiSettings: AndroidUiSettings(
              toolbarColor: Colors.deepOrange,
              toolbarTitle: "Ajustar Imagen",
              statusBarColor: Colors.deepOrange.shade900,
              backgroundColor: Colors.white));
      setState(() {
        _image = croppedImage;
      });
    }
    Navigator.pop(context);
  }
}


class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  final File photo;
  final double minHeight;
  final double maxHeight;
  final VoidCallback onPressed;
  final bool hideButtonWhenExpanded;

  _SliverAppBarDelegate(this.photo,
      {@required this.minHeight,
      @required this.maxHeight,
      this.onPressed,
      this.hideButtonWhenExpanded = true});

  @override
  double get minExtent => minHeight;
  @override
  double get maxExtent => math.max(maxHeight, minHeight);
  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    final appBarSize = maxHeight - shrinkOffset;
    final proportion = 2 - (maxHeight / appBarSize);
    final percent = proportion < 0 || proportion > 1 ? 0.0 : proportion;
    return Flex(
      direction: Axis.vertical,
      children: <Widget>[
        Flexible(
          child: Container(
            width: MediaQuery.of(context).size.width,
            color: Colors.white,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Flexible(
                  flex: 8,
                  child: CircleAvatar(
                    minRadius: 20.0,
                    maxRadius:
                        75.0 * proportion > 20 ? 75.0 * proportion : 20.0,
                    child: ClipOval(
                      child: photo == null
                          ? Image.asset(
                              'assets/images/pan.png',
                              fit: BoxFit.cover,
                            )
                          : Image.file(
                              photo,
                              fit: BoxFit.contain,
                            ),
                    ),
                    backgroundColor: Colors.grey[500],
                  ),
                ),
                Flexible(
                  flex: 2,
                  child: Opacity(
                    opacity: percent,
                    child: FlatButton(
                      onPressed: onPressed,
                      child: Text(
                        'Add Photo',
                        style: TextStyle(
                            color: Colors.blue, fontSize: 14.0 * proportion),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
        Divider(
          height: 1,
          thickness: 0.5,
        ),
      ],
    );
  }

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
           minHeight != oldDelegate.minHeight;
  }
}

I know there are several ways to solve this, which one do you advise me and why?
thanks for your help

Solution

Change this part from the sliverappbardelegate :

@override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
           minHeight != oldDelegate.minHeight || photo != oldDelegate.photo;
  }

Answered By – Mathis Fouques

Answer Checked By – Candace Johnson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.