|
|
@ -15,14 +15,14 @@ import 'package:flutter/widgets.dart';
|
|
|
|
|
|
|
|
|
|
|
|
/// cache gif fetched image
|
|
|
|
/// cache gif fetched image
|
|
|
|
class GifCache{
|
|
|
|
class GifCache{
|
|
|
|
final Map<String,List<ImageInfo>> caches= Map();
|
|
|
|
final Map<String,List<ImageInfo>?> caches= Map();
|
|
|
|
|
|
|
|
|
|
|
|
void clear() {
|
|
|
|
void clear() {
|
|
|
|
caches.clear();
|
|
|
|
caches.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool evict(Object key) {
|
|
|
|
bool evict(Object key) {
|
|
|
|
final List<ImageInfo> pendingImage = caches.remove(key);
|
|
|
|
final List<ImageInfo>? pendingImage = caches.remove(key);
|
|
|
|
if(pendingImage!=null){
|
|
|
|
if(pendingImage!=null){
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -34,11 +34,11 @@ class GifCache{
|
|
|
|
class GifController extends AnimationController{
|
|
|
|
class GifController extends AnimationController{
|
|
|
|
|
|
|
|
|
|
|
|
GifController({
|
|
|
|
GifController({
|
|
|
|
@required TickerProvider vsync,
|
|
|
|
required TickerProvider vsync,
|
|
|
|
double value=0.0,
|
|
|
|
double value=0.0,
|
|
|
|
Duration reverseDuration,
|
|
|
|
Duration? reverseDuration,
|
|
|
|
Duration duration,
|
|
|
|
Duration? duration,
|
|
|
|
AnimationBehavior animationBehavior
|
|
|
|
AnimationBehavior? animationBehavior
|
|
|
|
}):super.unbounded(
|
|
|
|
}):super.unbounded(
|
|
|
|
value:value,
|
|
|
|
value:value,
|
|
|
|
reverseDuration:reverseDuration,
|
|
|
|
reverseDuration:reverseDuration,
|
|
|
@ -57,8 +57,8 @@ class GifController extends AnimationController{
|
|
|
|
|
|
|
|
|
|
|
|
class GifImage extends StatefulWidget{
|
|
|
|
class GifImage extends StatefulWidget{
|
|
|
|
GifImage({
|
|
|
|
GifImage({
|
|
|
|
@required this.image,
|
|
|
|
required this.image,
|
|
|
|
@required this.controller,
|
|
|
|
required this.controller,
|
|
|
|
this.semanticLabel,
|
|
|
|
this.semanticLabel,
|
|
|
|
this.excludeFromSemantics = false,
|
|
|
|
this.excludeFromSemantics = false,
|
|
|
|
this.width,
|
|
|
|
this.width,
|
|
|
@ -73,20 +73,20 @@ class GifImage extends StatefulWidget{
|
|
|
|
this.matchTextDirection = false,
|
|
|
|
this.matchTextDirection = false,
|
|
|
|
this.gaplessPlayback = false,
|
|
|
|
this.gaplessPlayback = false,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
final VoidCallback onFetchCompleted;
|
|
|
|
final VoidCallback? onFetchCompleted;
|
|
|
|
final GifController controller;
|
|
|
|
final GifController controller;
|
|
|
|
final ImageProvider image;
|
|
|
|
final ImageProvider image;
|
|
|
|
final double width;
|
|
|
|
final double? width;
|
|
|
|
final double height;
|
|
|
|
final double? height;
|
|
|
|
final Color color;
|
|
|
|
final Color? color;
|
|
|
|
final BlendMode colorBlendMode;
|
|
|
|
final BlendMode? colorBlendMode;
|
|
|
|
final BoxFit fit;
|
|
|
|
final BoxFit? fit;
|
|
|
|
final AlignmentGeometry alignment;
|
|
|
|
final AlignmentGeometry alignment;
|
|
|
|
final ImageRepeat repeat;
|
|
|
|
final ImageRepeat repeat;
|
|
|
|
final Rect centerSlice;
|
|
|
|
final Rect? centerSlice;
|
|
|
|
final bool matchTextDirection;
|
|
|
|
final bool matchTextDirection;
|
|
|
|
final bool gaplessPlayback;
|
|
|
|
final bool gaplessPlayback;
|
|
|
|
final String semanticLabel;
|
|
|
|
final String? semanticLabel;
|
|
|
|
final bool excludeFromSemantics;
|
|
|
|
final bool excludeFromSemantics;
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@override
|
|
|
@ -98,12 +98,12 @@ class GifImage extends StatefulWidget{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class GifImageState extends State<GifImage>{
|
|
|
|
class GifImageState extends State<GifImage>{
|
|
|
|
List<ImageInfo> _infos;
|
|
|
|
List<ImageInfo>? _infos;
|
|
|
|
int _curIndex = 0;
|
|
|
|
int _curIndex = 0;
|
|
|
|
bool _fetchComplete= false;
|
|
|
|
bool _fetchComplete= false;
|
|
|
|
ImageInfo get _imageInfo {
|
|
|
|
ImageInfo? get _imageInfo {
|
|
|
|
if(!_fetchComplete)return null;
|
|
|
|
if(!_fetchComplete)return null;
|
|
|
|
return _infos==null?null:_infos[_curIndex];
|
|
|
|
return _infos==null?null:_infos![_curIndex];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -131,7 +131,7 @@ class GifImageState extends State<GifImage>{
|
|
|
|
_fetchComplete=true;
|
|
|
|
_fetchComplete=true;
|
|
|
|
_curIndex = widget.controller.value.toInt();
|
|
|
|
_curIndex = widget.controller.value.toInt();
|
|
|
|
if(widget.onFetchCompleted!=null){
|
|
|
|
if(widget.onFetchCompleted!=null){
|
|
|
|
widget.onFetchCompleted();
|
|
|
|
widget.onFetchCompleted!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -162,7 +162,7 @@ class GifImageState extends State<GifImage>{
|
|
|
|
_fetchComplete=true;
|
|
|
|
_fetchComplete=true;
|
|
|
|
_curIndex = widget.controller.value.toInt();
|
|
|
|
_curIndex = widget.controller.value.toInt();
|
|
|
|
if(widget.onFetchCompleted!=null){
|
|
|
|
if(widget.onFetchCompleted!=null){
|
|
|
|
widget.onFetchCompleted();
|
|
|
|
widget.onFetchCompleted!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -203,16 +203,16 @@ HttpClient get _httpClient {
|
|
|
|
HttpClient client = _sharedHttpClient;
|
|
|
|
HttpClient client = _sharedHttpClient;
|
|
|
|
assert(() {
|
|
|
|
assert(() {
|
|
|
|
if (debugNetworkImageHttpClientProvider != null)
|
|
|
|
if (debugNetworkImageHttpClientProvider != null)
|
|
|
|
client = debugNetworkImageHttpClientProvider();
|
|
|
|
client = debugNetworkImageHttpClientProvider!();
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}());
|
|
|
|
}());
|
|
|
|
return client;
|
|
|
|
return client;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Future<List<ImageInfo>> fetchGif(ImageProvider provider) async{
|
|
|
|
Future<List<ImageInfo>?> fetchGif(ImageProvider provider) async{
|
|
|
|
List<ImageInfo> infos = [];
|
|
|
|
List<ImageInfo>? infos = [];
|
|
|
|
dynamic data;
|
|
|
|
late dynamic data;
|
|
|
|
String key =provider is NetworkImage?provider.url:provider is AssetImage?provider.assetName:provider is MemoryImage?provider.bytes.toString():"";
|
|
|
|
String key =provider is NetworkImage?provider.url:provider is AssetImage?provider.assetName:provider is MemoryImage?provider.bytes.toString():"";
|
|
|
|
if(GifImage.cache.caches.containsKey(key)){
|
|
|
|
if(GifImage.cache.caches.containsKey(key)){
|
|
|
|
infos = GifImage.cache.caches[key];
|
|
|
|
infos = GifImage.cache.caches[key];
|
|
|
@ -240,7 +240,7 @@ Future<List<ImageInfo>> fetchGif(ImageProvider provider) async{
|
|
|
|
data = provider.bytes;
|
|
|
|
data = provider.bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ui.Codec codec=await PaintingBinding.instance.instantiateImageCodec(data.buffer.asUint8List());
|
|
|
|
ui.Codec codec=await PaintingBinding.instance!.instantiateImageCodec(data.buffer.asUint8List());
|
|
|
|
infos = [];
|
|
|
|
infos = [];
|
|
|
|
for(int i = 0;i<codec.frameCount;i++){
|
|
|
|
for(int i = 0;i<codec.frameCount;i++){
|
|
|
|
FrameInfo frameInfo = await codec.getNextFrame();
|
|
|
|
FrameInfo frameInfo = await codec.getNextFrame();
|
|
|
|