Flutter图片增强功能插件extended_image的使用
Flutter图片增强功能插件extended_image的使用
extended_image
ExtendedImage 是一个强大的Flutter图像扩展库,支持加载占位图(loading)/失败状态、缓存网络图片、缩放平移图片、照片查看器、滑出页面、编辑器(裁剪、旋转、翻转)、自定义绘制等功能。
Web演示
目录
导入
Null Safety版本
environment:
sdk: '>=2.12.0 <3.0.0'
flutter: '>=2.0'
dependencies:
extended_image: ^4.0.0
非Null Safety版本
environment:
sdk: '>=2.6.0 <2.12.0'
flutter: '>1.17.0 <=1.22.6'
dependencies:
extended_image: ^3.0.0-non-null-safety
缓存网络图片
简单使用
你可以像使用Image Widget一样使用ExtendedImage.network
ExtendedImage.network(
url,
width: ScreenUtil.instance.setWidth(400),
height: ScreenUtil.instance.setHeight(400),
fit: BoxFit.fill,
cache: true,
border: Border.all(color: Colors.red, width: 1.0),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(30.0)),
)
使用ExtendedNetworkImageProvider
ExtendedNetworkImageProvider(
this.url, {
this.scale = 1.0,
this.headers,
this.cache: false,
this.retries = 3,
this.timeLimit,
this.timeRetry = const Duration(milliseconds: 100),
CancellationToken cancelToken,
}) : assert(url != null),
assert(scale != null),
cancelToken = cancelToken ?? CancellationToken();
参数 | 描述 | 默认值 |
---|---|---|
url | 图片的URL | required |
scale | 放置在ImageInfo对象中的比例 | 1.0 |
headers | 用于通过HttpClient.get从网络获取图片时使用的HTTP头部信息 | - |
cache | 是否将图片缓存到本地 | false |
retries | 请求重试次数 | 3 |
timeLimit | 请求图片的时间限制 | - |
timeRetry | 请求重试的时间间隔 | milliseconds: 100 |
cancelToken | 取消网络请求的令牌 | CancellationToken() |
你可以创建新的提供者并继承ExtendedProvider,并覆盖instantiateImageCodec方法。这样你就可以在这里处理原始图片数据(压缩图片)。
加载状态
Extended Image 提供了三种状态(loading, completed, failed),你可以通过loadStateChanged回调定义自己的状态Widget。
ExtendedImage.network(
url,
loadStateChanged: (ExtendedImageState state) {
switch (state.extendedImageLoadState) {
case LoadState.loading:
return Image.asset("assets/loading.gif", fit: BoxFit.fill);
case LoadState.completed:
return FadeTransition(
opacity: _controller,
child: ExtendedRawImage(
image: state.extendedImageInfo?.image,
width: ScreenUtil.instance.setWidth(600),
height: ScreenUtil.instance.setHeight(400),
),
);
case LoadState.failed:
return GestureDetector(
child: Stack(
fit: StackFit.expand,
children: [
Image.asset("assets/failed.jpg", fit: BoxFit.fill),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Text(
"load image failed, click to reload",
textAlign: TextAlign.center,
),
)
],
),
onTap: () {
state.reLoadImage();
},
);
}
},
)
缩放平移
双击动画
onDoubleTap: (ExtendedImageGestureState state) {
var pointerDownPosition = state.pointerDownPosition;
double begin = state.gestureDetails.totalScale;
double end;
_animation?.removeListener(animationListener);
_animationController.stop();
_animationController.reset();
if (begin == doubleTapScales[0]) {
end = doubleTapScales[1];
} else {
end = doubleTapScales[0];
}
animationListener = () {
state.handleDoubleTap(
scale: _animation.value,
doubleTapPosition: pointerDownPosition);
};
_animation = _animationController
.drive(Tween<double>(begin: begin, end: end));
_animation.addListener(animationListener);
_animationController.forward();
},
编辑器
ExtendedImage.network(
imageTestUrl,
fit: BoxFit.contain,
mode: ExtendedImageMode.editor,
initEditorConfigHandler: (state) {
return EditorConfig(
maxScale: 8.0,
cropRectPadding: EdgeInsets.all(20.0),
hitTestSize: 20.0,
cropAspectRatio: _aspectRatio.aspectRatio,
);
},
);
裁剪数据
Dart库(stable)
-
在
pubspec.yaml
中添加依赖:dependencies: image: any
-
获取裁剪矩形和原始图片数据:
final Rect cropRect = state.getCropRect(); var data = state.rawImageData;
-
将原始图片数据转换为image库的数据:
final lb = await loadBalancer; Image src = await lb.run<Image, List<int>>(decodeImage, data);
-
对数据进行裁剪、翻转、旋转:
image = bakeOrientation(image); if (editAction.hasRotateDegrees) { image = copyRotate(image, angle: editAction.rotateDegrees); } if (editAction.flipY) { image = flip(image, direction: FlipDirection.horizontal); } if (editAction.needCrop) { image = copyCrop( image, x: cropRect.left.toInt(), y: cropRect.top.toInt(), width: cropRect.width.toInt(), height: cropRect.height.toInt(), ); }
-
转换回原始图片数据:
var fileData = await lb.run<List<int>, Image>(encodeJpg, src);
原生库(faster)
-
在
pubspec.yaml
中添加依赖:dependencies: image_editor: any
-
获取裁剪矩形和原始图片数据:
final Rect cropRect = state.getCropRect(); var data = state.rawImageData;
-
准备裁剪选项:
if (action.hasRotateDegrees) { final int rotateDegrees = action.rotateDegrees.toInt(); option.addOption(RotateOption(rotateDegrees)); } if (action.flipY) { option.addOption(const FlipOption(horizontal: true, vertical: false)); } if (action.needCrop) { Rect cropRect = imageEditorController.getCropRect()!; option.addOption(ClipOption.fromRect(cropRect)); }
-
使用editImage进行裁剪:
final result = await ImageEditor.editImage( image: img, imageEditorOption: option, );
照片查看器
ExtendedImageGesturePageView.builder(
itemBuilder: (BuildContext context, int index) {
var item = widget.pics[index].picUrl;
Widget image = ExtendedImage.network(
item,
fit: BoxFit.contain,
mode: ExtendedImageMode.gesture,
gestureConfig: GestureConfig(
inPageView: true, initialScale: 1.0,
cacheGesture: false
),
);
image = Container(
child: image,
padding: EdgeInsets.all(5.0),
);
if (index == currentIndex) {
return Hero(
tag: item + index.toString(),
child: image,
);
} else {
return image;
}
},
itemCount: widget.pics.length,
onPageChanged: (int index) {
currentIndex = index;
rebuild.add(index);
},
controller: PageController(
initialPage: currentIndex,
),
scrollDirection: Axis.horizontal,
),
滑出页面
启用滑出页面
return ExtendedImageSlidePage(
child: result,
slideAxis: SlideAxis.both,
slideType: SlideType.onlyImage,
onSlidingPage: (state) {
var showSwiper = !state.isSliding;
if (showSwiper != _showSwiper) {
_showSwiper = showSwiper;
rebuildSwiper.add(_showSwiper);
}
},
);
使用透明页面路由推送
Navigator.push(
context,
Platform.isAndroid
? TransparentMaterialPageRoute(builder: (_) => page)
: TransparentCupertinoPageRoute(builder: (_) => page),
);
边框、圆角、形状
ExtendedImage.network(
url,
width: ScreenUtil.instance.setWidth(400),
height: ScreenUtil.instance.setHeight(400),
fit: BoxFit.fill,
cache: true,
border: Border.all(color: Colors.red, width: 1.0),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(30.0)),
),
清除和保存
清除
// 清除磁盘缓存
clearDiskCachedImages(duration: const Duration(days: 7));
// 清除特定URL的磁盘缓存
clearDiskCachedImage(String url);
// 清除内存缓存
clearMemoryImageCache();
保存网络图片
saveNetworkImageToPhoto(String url, {bool useCache: true});
示例代码
以下是一个完整的示例Demo,展示了如何使用extended_image
插件来加载网络图片,并实现加载状态、缩放平移、编辑等功能。
import 'package:flutter/material.dart';
import 'package:extended_image/extended_image.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Extended Image Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Extended Image Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
final String imageUrl = 'https://photo.tuchong.com/4870004/f/298584322.jpg';
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
)..forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ExtendedImage.network(
imageUrl,
width: 300,
height: 300,
fit: BoxFit.cover,
cache: true,
loadStateChanged: (ExtendedImageState state) {
switch (state.extendedImageLoadState) {
case LoadState.loading:
return Image.asset("assets/loading.gif", fit: BoxFit.fill);
case LoadState.completed:
return FadeTransition(
opacity: _controller,
child: ExtendedRawImage(
image: state.extendedImageInfo?.image,
width: 300,
height: 300,
),
);
case LoadState.failed:
return GestureDetector(
child: Stack(
fit: StackFit.expand,
children: [
Image.asset("assets/failed.jpg", fit: BoxFit.fill),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Text(
"load image failed, click to reload",
textAlign: TextAlign.center,
),
)
],
),
onTap: () {
state.reLoadImage();
},
);
}
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullScreenImageViewer(imageUrl: imageUrl),
),
);
},
child: Text('View Full Screen'),
),
],
),
),
);
}
}
class FullScreenImageViewer extends StatefulWidget {
final String imageUrl;
FullScreenImageViewer({required this.imageUrl});
@override
_FullScreenImageViewerState createState() => _FullScreenImageViewerState();
}
class _FullScreenImageViewerState extends State<FullScreenImageViewer> {
final GlobalKey<ExtendedImageGestureState> _key = GlobalKey<ExtendedImageGestureState>();
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: ExtendedImage.network(
widget.imageUrl,
fit: BoxFit.contain,
mode: ExtendedImageMode.gesture,
initGestureConfigHandler: (state) {
return GestureConfig(
minScale: 0.9,
animationMinScale: 0.7,
maxScale: 3.0,
animationMaxScale: 3.5,
speed: 1.0,
inertialSpeed: 100.0,
initialScale: 1.0,
inPageView: false,
initialAlignment: InitialAlignment.center,
);
},
onDoubleTap: (ExtendedImageGestureState state) {
var pointerDownPosition = state.pointerDownPosition;
double begin = state.gestureDetails.totalScale;
double end;
_key.currentState?.animation?.removeListener(() {});
_key.currentState?.animationController.stop();
_key.currentState?.animationController.reset();
if (begin == 1.0) {
end = 2.0;
} else {
end = 1.0;
}
_key.currentState?.handleDoubleTap(
scale: end,
doubleTapPosition: pointerDownPosition,
);
_key.currentState?.animationController.forward();
},
heroBuilderForSlidingPage: (widget) {
return Hero(
tag: widget.imageUrl,
child: widget,
);
},
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}
这个示例展示了如何使用extended_image
插件加载网络图片,并实现了加载状态、缩放平移、全屏查看等功能。希望对你有所帮助!
更多关于Flutter图片增强功能插件extended_image的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图片增强功能插件extended_image的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,extended_image
是一个功能强大的 Flutter 插件,用于增强图片显示和处理功能。以下是如何在 Flutter 项目中使用 extended_image
的代码案例,包括一些基本的功能演示,如图片加载、缓存、点击放大等。
1. 添加依赖
首先,在你的 pubspec.yaml
文件中添加 extended_image
依赖:
dependencies:
flutter:
sdk: flutter
extended_image: ^x.x.x # 替换为最新版本号
然后运行 flutter pub get
来获取依赖。
2. 导入插件
在你的 Dart 文件中导入 extended_image
:
import 'package:extended_image/extended_image.dart';
3. 基本使用
以下是一个基本的使用示例,展示如何加载和显示一张图片:
import 'package:flutter/material.dart';
import 'package:extended_image/extended_image.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Extended Image Example'),
),
body: Center(
child: ExtendedImage.network(
'https://via.placeholder.com/600x400',
fit: BoxFit.cover,
),
),
),
);
}
}
4. 图片点击放大
extended_image
提供了点击图片放大的功能,下面是一个示例:
import 'package:flutter/material.dart';
import 'package:extended_image/extended_image.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Extended Image Zoom Example'),
),
body: Center(
child: ExtendedImage.network(
'https://via.placeholder.com/600x400',
mode: ExtendedImageMode.gesture, // 启用手势模式
fit: BoxFit.cover,
gestureConfig: GestureConfig(
minScale: 1.0,
maxScale: 3.0,
animationDuration: const Duration(milliseconds: 300),
),
),
),
),
);
}
}
5. 图片缓存
extended_image
默认支持图片缓存,但你也可以自定义缓存配置。以下是一个自定义缓存的示例:
import 'package:flutter/material.dart';
import 'package:extended_image/extended_image.dart';
import 'package:extended_image_library/extended_cache_image_provider.dart'; // 用于自定义缓存
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Extended Image Cache Example'),
),
body: Center(
child: ExtendedImage.network(
'https://via.placeholder.com/600x400',
cache: true, // 启用缓存
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.completed) {
// 图片加载完成后的处理
print('Image loaded successfully');
} else if (state.extendedImageLoadState == LoadState.failed) {
// 图片加载失败的处理
print('Failed to load image');
}
},
imageProvider: ExtendedCacheImageProvider(
'https://via.placeholder.com/600x400',
defaultCacheManager: DefaultCacheManager(), // 自定义缓存管理器
),
fit: BoxFit.cover,
),
),
),
);
}
}
在这个示例中,我们使用了 ExtendedCacheImageProvider
来自定义缓存配置。你需要确保已经导入了 extended_image_library
包。
6. 更多功能
extended_image
还提供了许多其他功能,如图片裁剪、滤镜、多图预览等。你可以查阅官方文档获取更多信息和高级用法。
以上代码案例展示了如何在 Flutter 项目中使用 extended_image
插件来实现图片增强功能。希望这些示例能帮助你快速上手并使用这个强大的插件。