Last active
May 4, 2022 10:56
-
-
Save DavBfr/a461c845871455e6d785248ded5a7982 to your computer and use it in GitHub Desktop.
ProxyImageProvider to lazily get the image dimensions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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