首页 > 解决方案 > 在按下另一个 Widget 时将 Widget 动画化回其预览状态

问题描述

我创建了一个选项卡小部件,可以按一个选项卡并突出显示和动画,但是在按下另一个选项卡后,预览选项卡应该动画回到它的预览状态。

使用打击代码在您的 IDE 上运行。

import 'package:flutter/material.dart';

class AnimatedTabsOne extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 300.0,
      height: 60.0,
      padding: EdgeInsets.all(8.0),
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(5.0),
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.black26,
              offset: Offset(0, 3.5),
//            spreadRadius: 0.0,
              blurRadius: 4.0,
            ),
          ]),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          BuildTab(),
          BuildTab(),
          BuildTab(),
        ],
      ),
    );
  }
}

class BuildTab extends StatefulWidget {
  @override
  _BuildTabState createState() => _BuildTabState();
}

class _BuildTabState extends State<BuildTab>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  bool isVisible = false;
  bool setActiveBackgroundColor = false;

  animateNow() {
    controller =
        AnimationController(duration: Duration(milliseconds: 200), vsync: this);
    controller.forward();
    animation = Tween<double>(begin: 50, end: 150).animate(controller)
      ..addListener(() => setState(() {
            setActiveBackgroundColor = true;
            isVisible = true;
          }));
//      ..addStatusListener((AnimationStatus status) {
//        if (status == AnimationStatus.completed) {
//          controller.reverse();
//          setState(() {
//            setActiveBackgroundColor = false;
//            isVisible = false;
//          });
//        }
//      });
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print(
        "setActiveBackgroundColor $setActiveBackgroundColor, isVisible: $isVisible");
    return InkWell(
      key: UniqueKey(),
      onTap: () => animateNow(),
      child: Container(
        width: animation?.value ?? 50,
        height: double.infinity,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(5.0),
          color: setActiveBackgroundColor == true ? Colors.blue : Colors.white,
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(Icons.home),
            Flexible(
              child: Visibility(visible: isVisible, child: Text("Home")),
            )
          ],
        ),
      ),
    );
  }
}

我尝试使用全局键,并以另一种方式调用回调函数,但它没有完成这项工作。

标签: flutterdartflutter-animation

解决方案


更好用AnimatedContainer。我简化了你的代码。有多种解决方案,一切都取决于你,但如果你只是那个功能,这是一个很好的模式,重建触发器最少:

class AnimatedTabsOne extends StatefulWidget {
  @override
  _AnimatedTabsOneState createState() => _AnimatedTabsOneState();
}

class _AnimatedTabsOneState extends State<AnimatedTabsOne> {
  int index;
  final myTabs = [BuildTab(), BuildTab(), BuildTab()];

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 300.0,
      height: 60.0,
      padding: EdgeInsets.all(8.0),
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(5.0),
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.black26,
              offset: Offset(0, 3.5),
//            spreadRadius: 0.0,
              blurRadius: 4.0,
            ),
          ]),
      child: Row(
        children: List<Widget>.from(
          myTabs.map((tab) {
            final index = myTabs.indexOf(tab);
            return GestureDetector(
              child: BuildTab(isVisible: this.index == index),
              onTap: () {
                if (this.index != index) {
                  setState(() {
                    this.index = index;
                  });
                }
              },
            );
          }),
        ),
      ),
    );
  }
}

class BuildTab extends StatelessWidget {
  final bool isVisible;

  BuildTab({this.isVisible = false});

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: Duration(milliseconds: 200),
      width: isVisible ? 150 : 50,
      height: double.infinity,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(5.0),
        color: isVisible ? Colors.blue : Colors.white,
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(Icons.home),
          Flexible(
            child: Visibility(visible: isVisible, child: Text("Home")),
          )
        ],
      ),
    );
  }
}

推荐阅读