Flutter实战一Flutter聊天应用(十一)
我们的应用程序现在可以点击查看图像,但还没有实现查看时放大、缩小与移动图像。要实现这个功能,需要监听用户在图像上的操作,并调用相应的回调处理用户操作。我们先将 class _ImageZoomableState extends State<ImageZoomable> {
//...
Widget _drawImage() {
if (_image == null) {
return null;
}
return new Transform(
transform: new Matrix4.diagonal3Values(1.0,1.0,1.0),child: new CustomPaint(
painter: new _ImageZoomablePainter(
image: _image,offset: Offset.zero,zoom: 1.0,)
)
);
}
//...
}
修改 class _ImageZoomableState extends State<ImageZoomable> {
//...
@override
Widget build(BuildContext context) {
return new GestureDetector(
child: _drawImage(),);
}
//...
}
图片缩放需要一个比例,在 class ImageZoomable extends StatefulWidget {
ImageZoomable(this.image,{Key key,this.scale = 2.0}) : super(key: key);
final ImageProvider image;
final double scale;
@override
_ImageZoomableState createState() => new _ImageZoomableState(scale);
}
在 class _ImageZoomableState extends State<ImageZoomable> {
_ImageZoomableState(this._scale);
final double _scale;
ImageStream _imageStream;
ui.Image _image;
Offset _startingFocalPoint;
Offset _previousOffset;
Offset _offset = Offset.zero;
double _zoom = 1.0;
double _previousZoom;
//...
}
现在我们可以修改 class _ImageZoomableState extends State<ImageZoomable> {
//...
Widget _drawImage() {
//...
return new Transform(
transform: new Matrix4.diagonal3Values(_scale,_scale,_scale),child: new CustomPaint(
painter: new _ImageZoomablePainter(
image: _image,offset: _offset,zoom: _zoom / _scale,)
)
);
}
//...
}
现在回到 class ChatMessage extends StatelessWidget {
//...
@override
Widget build(BuildContext context) {
return new SizeTransition(
//...
onTap: (){
Navigator.of(context).push( new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new ImageZoomable(
new NetworkImage(snapshot.value['imageUrl'])
);
}
));
},//...
);
}
}
我们要在用户对图像操作之前获取图像偏移位置相关的参数,也就是之前声明一些 手势监听器 class _ImageZoomableState extends State<ImageZoomable> {
//...
void _handleScaleStart(ScaleStartDetails details) {
if (_image == null) {
return;
}
_startingFocalPoint = details.focalPoint / _scale;
_previousOffset = _offset;
_previousZoom = _zoom;
}
//...
}
现在我们在 class _ImageZoomableState extends State<ImageZoomable> {
//...
@override
Widget build(BuildContext context) {
return new GestureDetector(
child: _drawImage(),onScaleStart: _handleScaleStart,);
}
//...
}
在用户对图像操作时,我们需要跟踪焦点的移动,并重新绘制图像。因此我们需要在
void _handleScaleUpdate(Size size,ScaleUpdateDetails details) {
if (_image == null) {
return;
}
double newZoom = _previousZoom * details.scale;
bool tooZoomedIn = _image.width * _scale / newZoom <= size.width ||
_image.height * _scale / newZoom <= size.height || newZoom <= 0.8;
if (tooZoomedIn) {
return;
}
setState(() {
_zoom = newZoom;
final Offset normalizedOffset = (_startingFocalPoint - _previousOffset) / _previousZoom;
_offset = details.focalPoint / _scale - normalizedOffset * _zoom;
});
}
上面定义了两个局部变量, 现在我们在 class _ImageZoomableState extends State<ImageZoomable> {
//...
@override
Widget build(BuildContext context) {
return new GestureDetector(
child: _drawImage(),onScaleUpdate: (d) => _handleScaleUpdate(context.size,d),);
}
//...
}
目前用户在查看图像时,需要点击系统的后退按钮才能返回到聊天屏幕。在大部分应用程序中,在查看图像时点击即可返回聊天屏幕,我们也可以这么做。在 class ImageZoomable extends StatefulWidget {
ImageZoomable(this.image,this.scale = 2.0,this.onTap}) : super(key: key);
final ImageProvider image;
final double scale;
final GestureTapCallback onTap;
@override
_ImageZoomableState createState() => new _ImageZoomableState(scale);
}
然后我们需要在 class _ImageZoomableState extends State<ImageZoomable> {
//...
@override
Widget build(BuildContext context) {
return new GestureDetector(
child: _drawImage(),onTap: widget.onTap,);
}
//...
}
最后回到 class ChatMessage extends StatelessWidget {
//...
@override
Widget build(BuildContext context) {
return new SizeTransition(
//...
onTap: (){
Navigator.of(context).push( new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new ImageZoomable(
new NetworkImage(snapshot.value['imageUrl']),onTap: (){
Navigator.of(context).pop();
},);
}
));
},//...
);
}
}
现在图像查看,且查看时可以缩放、移动图像的功能已经完成了! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |