颤动 - CustomPainter中从下到上的动画

时间:2017-08-16 14:20:52

标签: dart flutter

我试图在CustomPainter中创建一个动画,动画从下到上开始,但它从顶部开始。

点击FloatActionButton时,矩形应升至屏幕的最大高度,再次点按则返回最小尺寸。

我可以获得屏幕的大小,但我无法从底部向上插入此动画。你能救我吗?

enter image description here

import 'package:flutter/material.dart';
import 'dart:ui' as ui;

void main() {
  runApp(new MaterialApp(home: new HomePage()));
}

class HomePage extends StatefulWidget {
  @override
  HomePageState createState() => new HomePageState();
}

class HomePageState extends State<HomePage> with TickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;
  bool upDown = true;

  @override
  void initState() {
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 180),
    );

    _animation = new CurvedAnimation(
      parent: _controller,
      curve: new Interval(0.0, 1.0, curve: Curves.linear),
    );
  }

  @override
  Widget build(BuildContext context) {
    final ui.Size logicalSize = MediaQuery.of(context).size;
    final double _width = logicalSize.width;
    final double _height = logicalSize.height;

    void _up(){
      setState((){
        if(upDown) {
          upDown = false;
          _controller.forward(from: 0.0);
        } else {
          upDown = true;
          _controller.reverse(from: 1.0);
        }
      });
    }

    return new Scaffold(
        body: new Stack(
            children: <Widget>[
              new Positioned(
                  bottom: 0.0,
                  child: new AnimatedBuilder(
                    animation: _animation,
                    builder: (BuildContext context, Widget child) {
                    return new Container(
                      height: _height,
                      child: new CustomPaint(
                        painter: new Sky(_width, _height * _animation.value),
                        //child: new Text('$_height '+ _animation.value.toString()),
                      ),
                    );
                  },
                ),
              ),
              new Positioned(
                bottom: 16.0,
                right: 16.0,
                child: new FloatingActionButton(
                  backgroundColor: new Color(0xFFE57373),
                  child: new Icon(Icons.add),
                  onPressed: (){
                    _up();
                  },
                )
              )
            ]
        )
    );
  }
}

class Sky extends CustomPainter {
  final double _width;
  double _rectHeight;

  Sky(this._width, this._rectHeight);

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRect(
      new Rect.fromLTRB(
          0.0, 0.0, this._width, _rectHeight
      ),
      new Paint()..color = new Color(0xFF0099FF),
    );
  }

  @override
  bool shouldRepaint(Sky oldDelegate) {
    return _width != oldDelegate._width || _rectHeight != oldDelegate._rectHeight;
  }
}

1 个答案:

答案 0 :(得分:3)

您可以使用AnimatedBuilder执行此操作。另外,请确保提供shouldRepaint的有效实施。您的upDown成员变量应该是State的成员,而不是build函数的一部分。

screenshot

import 'package:flutter/material.dart';
import 'dart:ui' as ui;

void main() {
  runApp(new MaterialApp(home: new HomePage()));
}

class HomePage extends StatefulWidget {
  @override
  HomePageState createState() => new HomePageState();
}

class HomePageState extends State<HomePage> with TickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;
  bool upDown = true;

  @override
  void initState() {
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 180),
    );

    _animation = new CurvedAnimation(
      parent: _controller,
      curve: new Interval(0.0, 1.0, curve: Curves.linear),
    );
  }

  @override
  Widget build(BuildContext context) {
    final ui.Size logicalSize = MediaQuery.of(context).size;
    final double _width = logicalSize.width;
    final double _height = logicalSize.height;

    void _up(){
      setState((){
        if(upDown) {
          upDown = false;
          _controller.forward(from: 0.0);
        } else {
          upDown = true;
          _controller.reverse(from: 1.0);
        }
      });
    }

    return new Scaffold(
        body: new Stack(
            children: <Widget>[
              new Positioned(
                  bottom: 0.0,
                  child: new AnimatedBuilder(
                    animation: _animation,
                    builder: (BuildContext context, Widget child) {
                    return new Container(
                      height: _height,
                      child: new CustomPaint(
                        painter: new Sky(_width, _height * _animation.value),
                      ),
                    );
                  },
                ),
              ),
              new Positioned(
                bottom: 16.0,
                right: 16.0,
                child: new FloatingActionButton(
                  backgroundColor: new Color(0xFFE57373),
                  child: new Icon(Icons.add),
                  onPressed: (){
                    _up();
                  },
                )
              )
            ]
        )
    );
  }
}

class Sky extends CustomPainter {
  final double _width;
  double _rectHeight;

  Sky(this._width, this._rectHeight);

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRect(
      new Rect.fromLTRB(
          0.0, size.height - _rectHeight, this._width, size.height
      ),
      new Paint()..color = new Color(0xFF0099FF),
    );
  }

  @override
  bool shouldRepaint(Sky oldDelegate) {
    return _width != oldDelegate._width || _rectHeight != oldDelegate._rectHeight;
  }
}