Flutter 弹压的按钮 弹压的动画效果

import 'dart:ffi';

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;

  Animation<double> _animation;

  Animation<Offset> _slideAnimation;

  @override
  void initState() {
    super.initState();

    _animationController = new AnimationController(
        duration: Duration(milliseconds: 3000), vsync: this);

    _animationController.addListener(() {
      setState(() {});
    });

    _animation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
        parent: _animationController, curve: Curves.bounceInOut));

    _slideAnimation = Tween(begin: Offset(0, -0.5), end: Offset(0, 0)).animate(
        CurvedAnimation(
            parent: _animationController, curve: Curves.bounceInOut));

    _animationController.forward();
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
        body: Stack(
      children: [
        // 第一部分 底部的内容
        buildBottomMenu(),
        // 第二部分 按钮
        buildButtonFunction(),
        // 第二部分 文字
        buildText(),
      ],
    ));
  }

  buildBottomMenu() {
    return Positioned(
      height: 62,
      bottom: 0,
      left: 0,
      right: 0,
      child: Container(
        child: CustomPaint(
          painter: CustomMyPainter(_animation.value),
        ),
      ),
    );
  }

  buildText() {
    return Positioned(
        left: 0,
        right: 0,
        top: 120,
        child: Text(
          'hello world',
          textAlign: TextAlign.center,
          style: TextStyle(
              fontSize: 22,
              color: Colors.deepOrangeAccent,
              fontWeight: FontWeight.bold),
        ));
  }

  buildButtonFunction() {
    return Align(
      alignment: Alignment.bottomCenter,
      // 让按钮动起来
      child: SlideTransition(
        position: _slideAnimation,
        // 解决水波纹背景超出按钮区域
        child: Container(
          margin: EdgeInsets.only(bottom: 22),
          child: Ink(
            decoration: BoxDecoration(
              color: Colors.blue,
              borderRadius: BorderRadius.all(Radius.circular(30)),
            ),
            child: InkWell(
              borderRadius: BorderRadius.all(Radius.circular(30)),
              child: Container(
                 62,
                height: 62,
                // decoration: BoxDecoration(
                //     color: Colors.blue,
                //     borderRadius: BorderRadius.all(Radius.circular(30))),
                child: Icon(
                  Icons.add,
                  color: Colors.white,
                ),
              ),
              onTap: (){
                if(_animationController.isAnimating){
                  return;
                }
                if(_animationController.isCompleted){
                  _animationController.reverse();
                }else {
                  _animationController.reset();
                  _animationController.forward();
                }
              },
            ),
          ),
        ),
      ),
    );
  }
}

class CustomMyPainter extends CustomPainter {
  double progress;

  CustomMyPainter(this.progress);

  // 创建一个画笔
  Paint _paint = new Paint()..color = Colors.orangeAccent;

  @override
  void paint(Canvas canvas, Size size) {
    double width = size.width;
    double height = size.height;

    Path _path = new Path();

    _path.moveTo(0, 0);

    // 开始画三阶曲线
    _path.lineTo(width / 4 + width / 8 * progress, 0);

    double x1 = width / 4 + width / 8 * progress;
    double y1 = 64 * progress;

    double x2 = width / 2 + width / 8;
    double y2 = 64 * progress;

    double x3 = width / 2 + width * 2 / 8 - width / 8 * progress;
    double y3 = 0;

    _path.cubicTo(x1, y1, x2, y2, x3, y3);

    _path.lineTo(width, 0);
    _path.lineTo(width, height);
    _path.lineTo(0, height);

    _path.close();

    canvas.drawPath(_path, _paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
View Code

原文地址

原文地址:https://www.cnblogs.com/buyiblogs/p/14427123.html