Skip to content

Instantly share code, notes, and snippets.

@DavBfr
Last active May 4, 2022 10:56
Show Gist options
  • Save DavBfr/a461c845871455e6d785248ded5a7982 to your computer and use it in GitHub Desktop.
Save DavBfr/a461c845871455e6d785248ded5a7982 to your computer and use it in GitHub Desktop.
ProxyImageProvider to lazily get the image dimensions
// Test at:
// https://dartpad.dev/?id=a461c845871455e6d785248ded5a7982
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
// Initial dimensions, can be anything
double width = 0;
double height = 0;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Image(
width: width,
height: height,
image: ProxyImageProvider(
const NetworkImage('https://i.imgur.com/54Njk5Y.jpeg'),
(width, height) {
print('Image dimensions: $width x $height');
setState(() {
this.width = min(400.0, width.toDouble());
this.height = height * this.width / width;
});
print('Computed dimensions: ${this.width} x ${this.height}');
},
onError: (exception, stackTrace) {
print('Unable to load the image: $exception');
},
),
),
SizedBox(
width: width,
height: height,
child: const FlutterLogo(),
),
],
);
}
}
class ProxyImageProvider<T extends ImageProvider<S>, S extends Object>
extends ImageProvider<S> {
ProxyImageProvider(
this.imageProvider,
this.onSizeAvailable, {
this.onError,
});
final T imageProvider;
final void Function(int width, int height) onSizeAvailable;
final ImageErrorListener? onError;
@override
Future<S> obtainKey(ImageConfiguration configuration) {
return imageProvider.obtainKey(configuration);
}
@override
ImageStreamCompleter load(S key, DecoderCallback decode) {
final isc = imageProvider.load(key, decode);
late final ImageStreamListener listener;
listener = ImageStreamListener(
(image, synchronousCall) {
onSizeAvailable(image.image.width, image.image.height);
isc.removeListener(listener);
},
onError: (exception, stackTrace) {
isc.removeListener(listener);
onError?.call(exception, stackTrace);
},
);
isc.addListener(listener);
return isc;
}
@override
bool operator ==(dynamic other) {
return imageProvider == other;
}
@override
int get hashCode => imageProvider.hashCode;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment