组件 获取组件的宽度 使用 AnimatedRotation TweenAnimationBuilder 组合多个动画

71 阅读1分钟

微信截图_20230212204906.png

微信截图_20230212204922.png

/*
获取组件的宽度
globalKey0.currentContext!.size!.width
页面渲染后第一帧时的回调
WidgetsBinding.instance.addPostFrameCallback
动画的组合使用
TweenAnimationBuilder
AnimatedContainer
AnimatedRotation
 */
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  double turns = 90 / 360; // 转 90度
  Color color = Colors.black;
  GlobalKey globalKey0 = GlobalKey(),
      globalKey1 = GlobalKey(),
      globalKeyArrow = GlobalKey();
  late double innerW = -990, width0, width1, widthArrow, height = 0;
  final Duration duration = const Duration(milliseconds: 500);

  @override
  initState() {
    super.initState();
    // 渲染第一帧时的回调
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      width0 = globalKey0.currentContext!.size!.width;
      width1 = globalKey1.currentContext!.size!.width;
      widthArrow = globalKeyArrow.currentContext!.size!.width;
      setState(() {
        innerW = width0 - (width1 + widthArrow);
      });
    });
  }

  @override
  void didUpdateWidget(oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      backgroundColor: const Color(0xFF666666),
      body: Column(
        children: [
          Stack(
            children: [
              AnimatedContainer(
                duration: duration,
                transform: Matrix4.translationValues(innerW, 0, 0),
                child: Row(
                  children: [
                    TweenAnimationBuilder(
                        key: globalKey1,
                        tween: ColorTween(begin: Colors.black, end: color),
                        duration: duration,
                        builder: (context, Color? value, widget) {
                          return Text(
                            '副标题123123',
                            style: TextStyle(color: value, fontSize: 17),
                            strutStyle: const StrutStyle(leading: 1),
                          );
                        }),
                    Container(
                      key: globalKeyArrow,
                      width: 25,
                      height: 25,
                      margin: const EdgeInsets.only(left: 10),
                      alignment: Alignment.center,
                      decoration: const BoxDecoration(
                          borderRadius: BorderRadius.all(Radius.circular(25)),
                          color: Colors.grey),
                      child: AnimatedRotation(
                          turns: turns,
                          duration: duration,
                          child: TweenAnimationBuilder(
                              tween:
                                  ColorTween(begin: Colors.black, end: color),
                              duration: duration,
                              builder: (context, Color? value, widget) {
                                return Icon(
                                  Icons.arrow_forward_ios,
                                  size: 16,
                                  color: value,
                                );
                              })),
                    ),
                  ],
                ),
              ),
              Container(
                  key: globalKey0,
                  color: const Color(0xFF666666),
                  child: const Text(
                    '正标题',
                    style: TextStyle(color: Colors.black, fontSize: 17),
                    strutStyle: StrutStyle(leading: 1),
                  )),
            ],
          ),
          AnimatedContainer(
            duration: duration,
            height: height,
            width: double.infinity,
            color: Colors.greenAccent,
            alignment: Alignment.topCenter,
            child: const Text(
              '测试',
              style: TextStyle(fontSize: 38),
            ),
          )
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }

  void _incrementCounter() {
    setState(() {
      turns += 1 / 2;
      if (color == Colors.black) {
        color = Colors.red;
        innerW = width0;
        height = 100;
      } else {
        color = Colors.black;
        innerW = width0 - (width1 + widthArrow);
        height = 0;
      }
    });
  }
}