原创 

flutter 图片查看组件、支持缩放、轮转

分类:android    223人阅读    IT小君  2019-03-31 11:33
class NinePicture<T> extends PopupRoute<T> {
  final String barrierLabel;
  final List picList;
  final int index;
  int startX;
  int endX;

  NinePicture(this.picList, this.index, {this.barrierLabel});

  @override
  Duration get transitionDuration => Duration(milliseconds: 2000);

  @override
  @override
  Color get barrierColor => Colors.black54;

  @override
  bool get barrierDismissible => true;

  AnimationController _animationController;

  @override
  AnimationController createAnimationController() {
    assert(_animationController == null);
    _animationController =
        BottomSheet.createAnimationController(navigator.overlay);
    return _animationController;
  }

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    return MediaQuery.removePadding(
      removeTop: true,
      context: context,
      child: GestureDetector(
        child: AnimatedBuilder(
          animation: animation,
          builder: (BuildContext context, Widget child) => GestureDetector(
                onTap: () {
                  Navigator.pop(context);
                },
                child: _PictureWidget(picList, index),
              ),
        ),
      ),
    );
  }
}

class _PictureWidget extends StatefulWidget {
  final List picList;
  final int index;

  _PictureWidget(this.picList, this.index);

  @override
  State createState() {
    return _PictureWidgetState();
  }
}

class _PictureWidgetState extends State<_PictureWidget> with TickerProviderStateMixin{
  int startX = 0;
  int endX = 0;
  int index = 0;

  double _scale = 1.0;
  double _tmpScale = 1.0;
  double _moveX = 0.0;
  double _tmpMoveX = 0.0;
  double _moveY = 0.0;
  double _tmpMoveY = 0.0;
  double _rotation = 0.0;
  double _tmpRotation = 0.0;

  Offset _tmpFocal = Offset.zero;

  AnimationController _animationController;
  Animation<double> _values;

  @override
  void initState() {
    // TODO: implement initState

    _animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 120));
    // Tween 将动画的 0 - 1 的值映射到我们设置的范围内
    _values = Tween(begin: 1.0, end: 0.0).animate(_animationController);
    _animationController.addListener(() {
      setState(() {
        // 通过动画逐帧还原位置
        _moveX = _tmpMoveX * _values.value;
        _moveY = _tmpMoveY * _values.value;
        _scale = (_tmpScale - 1) * _values.value + 1;
        _rotation = _tmpRotation * _values.value;
      });
    });

    super.initState();
    index = widget.index;
  }

  @override
  void dispose() {
    _animationController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Matrix4 matrix4 = Matrix4.identity()
      ..scale(_scale, _scale)
      ..translate(_moveX, _moveY)
      ..rotateZ(_rotation);
    return new Material(
      color: Colors.transparent,
      child: new Container(
        width: double.infinity,
        child: Stack(
          children: <Widget>[
            GestureDetector(
              child: Center(
                child:Transform(
                    alignment: FractionalOffset.center,
                    transform: matrix4,
                    child: CachedNetworkImage(
                      imageUrl: widget.picList[index],
                      fit: BoxFit.cover,
                    )
                ),
              ),
              onHorizontalDragDown: (detail) {
                startX = detail.globalPosition.dx.toInt();
              },
              onHorizontalDragUpdate: (detail) {
                endX = detail.globalPosition.dx.toInt();
              },
              onHorizontalDragEnd: (detail) {
                _getIndex(endX - startX);
                setState(() {});
              },
              onHorizontalDragCancel: () {},
                onDoubleTap: () {
                  if (!_animationController.isAnimating) {
                    _tmpMoveX = _moveX;
                    _tmpMoveY = _moveY;
                    _tmpScale = _scale;
                    _tmpRotation = _rotation;
                    _animationController.reset();
                    _animationController.forward();
                  }
                },
                onScaleStart: (details) {
                  if (!_animationController.isAnimating) {
                    _tmpFocal = details.focalPoint;
                    _tmpMoveX = _moveX;
                    _tmpMoveY = _moveY;
                    _tmpScale = _scale;
                    _tmpRotation = _rotation;
                  }
                },
                onScaleUpdate: (details) {
                  if (!_animationController.isAnimating) {
                    setState(() {
                      _moveX = _tmpMoveX + (details.focalPoint.dx - _tmpFocal.dx) / _tmpScale;
                      _moveY = _tmpMoveY + (details.focalPoint.dy - _tmpFocal.dy) / _tmpScale;
                      _scale = _tmpScale * details.scale;
                      _rotation = _tmpRotation + details.rotation;
                      print(_rotation);
                    });
                  }
                }
            )
            ,
            Align(
              alignment: Alignment.bottomCenter,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: List.generate(
                  widget.picList.length,
                  (i) => GestureDetector(
                        child: CircleAvatar(
                          foregroundColor: Theme.of(context).primaryColor,
                          radius: 8.0,
                          backgroundColor: index == i
                              ? Theme.of(context).primaryColor
                              : Colors.white,
                        ),
                        onTap: () {
                          setState(() {
                            startX = endX = 0;
                            index = i;
                          });
                        },
                      ),
                ).toList(),
              ),
            )
          ],
        ),
        alignment: Alignment.center,
      ),
    );
  }

  void _getIndex(int delta) {
    if (delta > 50) {
      setState(() {
        index--;
        index = index.clamp(0, widget.picList.length - 1);
      });
    } else if (delta < 50) {
      setState(() {
        index++;
        index = index.clamp(0, widget.picList.length - 1);
      });
    }
  }
}


html5 canvas进度条圆环图表统计动画特效

HTML5 Canvas竖直流动线条背景动画特效

canvas炫酷鼠标移动文字粒子特效

响应式咖啡饮品宣传网站模板

HTML5现代家居装潢公司网站模板

现代时尚家具公司网站模板

中小型创意设计服务公司网站模板

css+js实现的颜色渐变数字时钟动画特效

jQuery右端悬浮带返回顶部特效

有机水果蔬菜HTML5网站模板

html5 svg夜空中星星流星动画场景特效

响应式时尚单品在线商城网站模板

html5图标下拉搜索框自动匹配代码

响应式太阳能能源公司网站模板

html5 canvas彩色碎片组合球形旋转动画特效

js+css3抽奖转盘旋转点餐代码

HTML5数字产品服务公司网站模板

css鼠标跟随文字模糊特效

小众时尚单品在线电子商务网站模板

网页设计开发公司网站模板

 工具推荐 更多»