1

Using CachedNetworkImage I have figured out how to use a callback method just before displaying the image:

imageUrl: input,
    imageBuilder: (context, imageProvider) {
      debugPrint('Image is loaded!');
      return Image(image: imageProvider);
    },

However, is there a way to get the image dimensions, specifically the height of the image at that point just before the image is displayed?

Mark
  • 3,653
  • 10
  • 30
  • 62

1 Answers1

1

Taking into account this answer on how to get a widgets size, you can come up with the following approach to resize the image cache in memory to about twice the widgets size. I've found that if you directly use the widgets size the image loses A LOT of sharpness. You would also probably start adding most of cachedNetworkImage attributes to AutoSizedCachedNetworkImage in order to have a more customizable widget.

TLDR:

This will adjust the image size after first frame.

class AutoSizedCachedNetworkImage extends StatefulWidget {
  final String url;
  const AutoSizedCachedNetworkImage({Key? key, required this.url}) : super(key: key);

  @override
  State<AutoSizedCachedNetworkImage> createState() => _AutoSizedCachedNetworkImageState();
}

class _AutoSizedCachedNetworkImageState extends State<AutoSizedCachedNetworkImage> {
  double? imageSizeWidth;
  double? imageSizeHeight;
  @override
  Widget build(BuildContext context) {
    return MeasureSize(
      onChange: (size) {
        if (mounted) {
          setState(() {
            imageSizeWidth = size.width * 2;
            imageSizeHeight = size.height * 2;
          });
        }
      },
      child: CachedNetworkImage(
        memCacheHeight: imageSizeHeight?.toInt(),
        memCacheWidth: imageSizeWidth?.toInt(),
        imageUrl: widget.url,
      ),
    );
  }
}

Code sourced from the other answer to get a widget's size

typedef void OnWidgetSizeChange(Size size);

class MeasureSizeRenderObject extends RenderProxyBox {
  Size? oldSize;
  final OnWidgetSizeChange onChange;

  MeasureSizeRenderObject(this.onChange);

  @override
  void performLayout() {
    super.performLayout();

    var newSize = child!.size;
    if (oldSize == newSize) return;

    oldSize = newSize;
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      onChange(newSize);
    });
  }
}

class MeasureSize extends SingleChildRenderObjectWidget {
  final OnWidgetSizeChange onChange;

  const MeasureSize({
    Key? key,
    required this.onChange,
    required Widget child,
  }) : super(key: key, child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return MeasureSizeRenderObject(onChange);
  }
}
croxx5f
  • 5,163
  • 2
  • 15
  • 36