Flutter带有SlideTransition的AnimatedSwitcher

3
在这段代码中,我尝试使用SlideTransition创建一个简单的递增数字,但它不能正常工作,我只能成功地使用ScaleTransition。这意味着我想要使用SlideTransition来增加数字。

所需创建的Gif示例:

请将second部分视为动画。

enter image description here

class TestScreen extends StatefulWidget {
  const TestScreen({super.key});

  @override
  State<TestScreen> createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen> with SingleTickerProviderStateMixin {
  int num = 0;
  late final AnimationController _animationController = AnimationController(
      duration: Duration(milliseconds: 750),
      vsync: this)
    ..forward();

  static final offset1 = Tween<Offset>(begin: Offset.zero, end: Offset(0, -1));
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Container(
        width: double.infinity,
        height: double.infinity,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            AnimatedSwitcher(
              duration: Duration(milliseconds: 1000),
              transitionBuilder: (child, animation) => SlideTransition(
                position: (offset1).animate(animation),
                child: child,
              ),
              child: Text(
                key: ValueKey(num),
                '$num',
                style: TextStyle(color: Colors.black, fontSize: 64.0),
              ),
            ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  num++;
                });
              },
              child: Text('increment'),
            ),
          ],
        ),
      ),
    );
  }
}

2
transitionBuilder 传递了一个你应该使用的动画,请参见 https://gist.github.com/pskink/d1f591eca19359c09d38bf8cc35df4ca#file-clock-dart-L79 - pskink
我是指您不能使用任何私有的 AnimationController _animationController 来为您的小部件添加动画效果。 - pskink
@pskink,有没有类似我想创建的东西的等效物?例如库,我试图制作一个简单的动画,当数字改变时产生幻灯片效果。 - DolDurma
AnimatedSwitcher非常灵活,可以制作各种过渡效果 - 只需像我在代码片段中所做的那样使用transitionBuilder即可。 - pskink
@pskink,但是那样并不正确。 - DolDurma
显示剩余8条评论
1个回答

1

enter image description here

import 'dart:async';

import 'package:flutter/material.dart';

void fileMain() {
  runApp(
    const MaterialApp(
      home: MyApp(),
    ),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late AnimationController animatedController;
  late Timer timer;

  double milliseconds = 0;

  @override
  void initState() {
    animatedController = AnimationController.unbounded(
      vsync: this,
    );
    super.initState();
    timer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
      milliseconds += 500;
      animatedController.animateTo(
        milliseconds,
        duration: const Duration(milliseconds: 500),
      );
    });
  }

  @override
  void dispose() {
    animatedController.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.only(left: 120),
          child: AnimatedBuilder(
            animation: animatedController,
            builder: (context, child) {
              final value = (animatedController.value / 100).ceil() / 10;
              final map = value.toString().trim().split(".");
              final animatedLetters = map[0].split("");
              return Row(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Container(
                      height: 10,
                      width: 10,
                      decoration: const BoxDecoration(
                          color: Colors.red, shape: BoxShape.circle)),
                  ...animatedLetters
                      .asMap()
                      .map(
                        (key, value) => MapEntry(
                          key,
                          AnimatedLetter(
                            key: ValueKey(key),
                            letter: value,
                          ),
                        ),
                      )
                      .values
                      .toList(),
                  Text(
                    '.${map[1]}',
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

class AnimatedLetter extends StatefulWidget {
  const AnimatedLetter({super.key, this.letter});

  final String? letter;

  @override
  State<AnimatedLetter> createState() => _AnimatedLetterState();
}

class _AnimatedLetterState extends State<AnimatedLetter>
    with SingleTickerProviderStateMixin {
  AnimationController? controller;

  String? currentLetter;
  String? prevLetter;

  @override
  void initState() {
    controller = AnimationController(
      duration: const Duration(milliseconds: 300),
      vsync: this,
    );
    currentLetter = widget.letter;
    prevLetter = widget.letter;
    super.initState();
  }

  @override
  void didUpdateWidget(AnimatedLetter oldWidget) {
    if (widget.letter != oldWidget.letter) {
      setState(() {
        prevLetter = oldWidget.letter;
        currentLetter = widget.letter;
        controller!
          ..reset()
          ..forward();
      });
    }

    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: AnimatedBuilder(
          animation: controller!,
          builder: (_, __) {
            return Stack(
              alignment: Alignment.centerRight,
              children: [
                Transform.translate(
                  offset: Offset(0, controller!.value * 20),
                  child: Opacity(
                    opacity: 1 - controller!.value,
                    child: Text(
                      prevLetter!,
                      textAlign: TextAlign.center,
                    ),
                  ),
                ),
                Transform.translate(
                  offset: Offset(0, -20 + controller!.value * 20),
                  child: Opacity(
                    opacity: controller!.value,
                    child: Text(
                      currentLetter!,
                      textAlign: TextAlign.center,
                    ),
                  ),
                ),
              ],
            );
          }),
    );
  }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接