|
- import 'dart:io';
- import 'dart:typed_data';
-
- import 'package:chat/chat/download_item.dart';
- import 'package:chat/generated/i18n.dart';
- import 'package:chat/models/ChatMsg.dart';
- import 'package:flutter/material.dart';
- import 'package:image_gallery_saver/image_gallery_saver.dart';
- import 'package:oktoast/oktoast.dart';
-
- import '../r.dart';
-
- class PhotoPage extends StatefulWidget {
- final MsgModel msg;
- PhotoPage({this.msg});
- @override
- _PhotoPageState createState() => _PhotoPageState();
- }
-
- class _PhotoPageState extends State<PhotoPage>
- with SingleTickerProviderStateMixin {
- AnimationController _controller;
- Animation<Offset> _animation;
- Offset _offset = Offset.zero;
- double _scale = 1.0;
- Offset _normalizedOffset;
- double _previousScale;
- double _kMinFlingVelocity = 600.0;
-
- ImageProvider provider;
-
- @override
- void initState() {
- super.initState();
-
- getImgData();
- _controller = AnimationController(vsync: this);
- _controller.addListener(() {
- setState(() {
- _offset = _animation.value;
- });
- });
- }
-
- getImgData() {
- if (widget.msg.localFile != null) {
- var fileData = File(widget.msg.localFile).readAsBytesSync();
- provider = MemoryImage(fileData);
- } else {
- provider = MemoryImage(Uint8List.fromList(widget.msg.msgContent));
- }
- }
-
- @override
- void dispose() {
- _controller.stop();
- _controller.dispose();
-
- super.dispose();
- }
-
- Offset _clampOffset(Offset offset) {
- final Size size = context.size;
- // widget的屏幕宽度
- final Offset minOffset = Offset(size.width, size.height) * (1.0 - _scale);
- // 限制他的最小尺寸
- return Offset(
- offset.dx.clamp(minOffset.dx, 0.0), offset.dy.clamp(minOffset.dy, 0.0));
- }
-
- void _handleOnScaleStart(ScaleStartDetails details) {
- setState(() {
- _previousScale = _scale;
- _normalizedOffset = (details.focalPoint - _offset) / _scale;
- // 计算图片放大后的位置
- _controller.stop();
- });
- }
-
- void _handleOnScaleUpdate(ScaleUpdateDetails details) {
- setState(() {
- _scale = (_previousScale * details.scale).clamp(1.0, 3.0);
- // 限制放大倍数 1~3倍
- _offset = _clampOffset(details.focalPoint - _normalizedOffset * _scale);
- // 更新当前位置
- });
- }
-
- void _handleOnScaleEnd(ScaleEndDetails details) {
- final double magnitude = details.velocity.pixelsPerSecond.distance;
- if (magnitude < _kMinFlingVelocity) return;
- final Offset direction = details.velocity.pixelsPerSecond / magnitude;
- // 计算当前的方向
- final double distance = (Offset.zero & context.size).shortestSide;
- // 计算放大倍速,并相应的放大宽和高,比如原来是600*480的图片,放大后倍数为1.25倍时,宽和高是同时变化的
- _animation = _controller.drive(Tween<Offset>(
- begin: _offset, end: _clampOffset(_offset + direction * distance)));
- _controller
- ..value = 0.0
- ..fling(velocity: magnitude / 1000.0);
- }
-
- @override
- Widget build(BuildContext context) {
- return GestureDetector(
- onTap: () {
- Navigator.pop(context);
- },
- onScaleStart: _handleOnScaleStart,
- onScaleUpdate: _handleOnScaleUpdate,
- onScaleEnd: _handleOnScaleEnd,
- child: Material(
- child: DownloadItem(
- msg: widget.msg,
- isAutoDown: false,
- onComplete: () {
- getImgData();
- setState(() {});
- },
- child: Transform(
- transform: Matrix4.identity()
- ..translate(_offset.dx, _offset.dy)
- ..scale(_scale),
- child: Stack(
- children: <Widget>[
- Image(
- fit: BoxFit.fitWidth,
- image: provider ?? AssetImage(R.assetsImagesIcAlbum),
- ),
-
- Positioned(
- right: 10,
- bottom: 10,
- child: InkWell(
- onTap: saveToGallery,
- child: Container(
- padding: EdgeInsets.all(5),
- decoration: BoxDecoration(
- color: Colors.grey.withAlpha(150),
- borderRadius: BorderRadius.circular(8)),
- child: Icon(Icons.save_alt, color: Colors.white70),
- )))
- ],
- )),
- )),
- );
- }
-
- saveToGallery() async {
- if (widget.msg.localFile != null) {
- var data= File(widget.msg.localFile).readAsBytesSync();
- ImageGallerySaver.saveImage(data).then((res) {
- print(res);
- if (res != null) {
- showToast(I18n.of(context).successfully_saved);
- }
- });
- } else {
- ImageGallerySaver.saveImage(Uint8List.fromList(widget.msg.msgContent))
- .then((res) {
- print(res);
- if (res != null) {
- showToast(I18n.of(context).successfully_saved);
- }
- });
- }
- }
- }
|