web-dev-qa-db-fra.com

comment animer des éléments de repli en flottement

Comment puis-je développer et réduire le widget lorsque l'utilisateur appuie sur un widget différent (frère ou parent) avec une animation?

new Column(
    children: <Widget>[
        new header.IngridientHeader(
            new Icon(
                Icons.fiber_manual_record,
                color: AppColors.primaryColor
            ),
            'Voice Track 1'
        ),
        new Grid()
    ],
)

Je veux que l'utilisateur puisse appuyer sur l'en-tête.IngridientHeader, puis le widget Grid doit basculer (masquer s'il est visible et inversement)

éditer:

im essayant de faire quelque chose qui dans bootstrap s'appelle Collapse. getbootstrap.com/docs/4.0/components/collapse

edit 2: header.IngridientHeader devrait rester en place tout le temps que le widget Grid () est déroulant (horizontal).

12
Dariusz Włodarz

Si vous souhaitez réduire un widget à une hauteur ou une largeur nulle qui a un enfant qui déborde lorsqu'il est réduit, je recommanderais SizeTransition ou ScaleTransition .

Voici un exemple du widget ScaleTransition utilisé pour réduire le conteneur pour les quatre boutons noirs et le texte d'état. Mon widget ExpandedSection est utilisé avec une colonne pour obtenir la structure suivante. An example of the ScaleTransition widget

Un exemple de widget qui utilise une animation avec le widget SizeTransition:

class ExpandedSection extends StatefulWidget {

  final Widget child;
  final bool expand;
  ExpandedSection({this.expand = false, this.child});

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

class _ExpandedSectionState extends State<ExpandedSection> with SingleTickerProviderStateMixin {
  AnimationController expandController;
  Animation<double> animation; 

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

  ///Setting up the animation
  void prepareAnimations() {
    expandController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 500)
    );
    Animation curve = CurvedAnimation(
      parent: expandController,
      curve: Curves.fastOutSlowIn,
    );
    animation = Tween(begin: 0.0, end: 1.0).animate(curve)
      ..addListener(() {
        setState(() {

        });
      }
    );
  }

  @override
  void didUpdateWidget(ExpandedSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    if(widget.expand) {
      expandController.forward();
    }
    else {
      expandController.reverse();
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return SizeTransition(
      axisAlignment: 1.0,
      sizeFactor: animation,
      child: widget.child
    );
  }
}

AnimatedContainer fonctionne également mais Flutter peut se plaindre d'un débordement si l'enfant n'est pas redimensionnable à une largeur ou une hauteur zéro.

18
Adam Jonsson

Alternativement, vous pouvez simplement utiliser un AnimatedContainer pour imiter ce comportement.

enter image description here

class AnimateContentExample extends StatefulWidget {
  @override
  _AnimateContentExampleState createState() => new _AnimateContentExampleState();
}

class _AnimateContentExampleState extends State<AnimateContentExample> {
  double _animatedHeight = 100.0;
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text("Animate Content"),),
      body: new Column(
        children: <Widget>[
          new Card(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                new GestureDetector(
                  onTap: ()=>setState((){
                    _animatedHeight!=0.0?_animatedHeight=0.0:_animatedHeight=100.0;}),
                  child:  new Container(
                  child: new Text("CLICK ME"),
                  color: Colors.blueAccent,
                  height: 25.0,
                    width: 100.0,
                ),),
                new AnimatedContainer(duration: const Duration(milliseconds: 120),
                  child: new Text("Toggle Me"),
                  height: _animatedHeight,
                  color: Colors.tealAccent,
                  width: 100.0,
                )
              ],
            ) ,
          )
        ],
      ),
    );
  }
}
8
aziza

Je pense que vous cherchez ExpansionTile widget. Cela prend une propriété title qui est équivalente à l'en-tête et à la propriété children à laquelle vous pouvez passer des widgets à afficher ou masquer lors de la bascule. Vous pouvez trouver un exemple de la façon de l'utiliser ici .

Exemple d'utilisation simple:

new ExpansionTile(title: new Text("Numbers"),
      children: <Widget>[
        new Text("Number: 1"),
        new Text("Number: 2"),
        new Text("Number: 3"),
        new Text("Number: 4"),
        new Text("Number: 5")
      ],
),

J'espère que cela pourra aider!

2
Hemanth Raj

Sortie:

enter image description here


Code:

class _HomePageState extends State<HomePage> {
  Duration _duration = Duration(seconds: 1);
  int _flex1 = 1, _flex2 = 1, _flex3 = 1;

  @override
  Widget build(BuildContext context) {
    var data = MediaQuery.of(context);
    double height = data.size.height - data.padding.top - kToolbarHeight;
    var height1 = (_flex1 * height) / (_flex1 + _flex2 + _flex3);
    var height2 = (_flex2 * height) / (_flex1 + _flex2 + _flex3);
    var height3 = (_flex3 * height) / (_flex1 + _flex2 + _flex3);

    return Scaffold(
      appBar: AppBar(
        title: Text("Awesome Effect"),
      ),
      body: Column(
        children: <Widget>[
          AnimatedContainer(
            duration: _duration,
            color: Colors.blue,
            height: height1,
            alignment: Alignment.center,
            child: Text("Flex: ${_flex1}", style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold)),
          ),
          AnimatedContainer(
            duration: _duration,
            color: Colors.red,
            height: height2,
            alignment: Alignment.center,
            child: Text("Flex: ${_flex2}", style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold)),
          ),
          AnimatedContainer(
            duration: _duration,
            color: Colors.teal,
            height: height3,
            alignment: Alignment.center,
            child: Text("Flex: ${_flex3}", style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold)),
          ),
        ],
      ),
    );
  }
}
0
CopsOnRoad