Flutter rende semplice il menu di Facebook

Oct 27 2020

In Flutterche sto cercando di fare un semplice Facebookmenù, in seguito schermata abbiamo una widget di numero e quando scatto su questo, widget di cui cioè al di sotto del widget di corrente, deve essere ridimensionato e crescere e che mostra un altro icone in quella

questo codice sottostante che ho introdotto funziona bene, ma non ha un contenitore in background

in referenziato il collegamento Columnutilizzato e l'ho cambiato in Stacke non funziona correttamente

riferimento

import 'package:flutter/material.dart';

class FancyFab extends StatefulWidget {
  final Function() onPressed;
  final String tooltip;
  final IconData icon;

  FancyFab({this.onPressed, this.tooltip, this.icon});

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

class _FancyFabState extends State<FancyFab>
    with SingleTickerProviderStateMixin {
  bool isOpened = false;
  AnimationController _animationController;
  Animation<Color> _buttonColor;
  Animation<double> _animateIcon;
  Animation<double> _translateButton;
  Curve _curve = Curves.easeOut;
  double _fabHeight = 56.0;

  @override
  initState() {
    _animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500))
          ..addListener(() {
            setState(() {});
          });
    _animateIcon =
        Tween<double>(begin: 0.0, end: 1.0).animate(_animationController);
    _buttonColor = ColorTween(
      begin: Colors.blue,
      end: Colors.red,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Interval(
        0.00,
        1.00,
        curve: Curves.linear,
      ),
    ));
    _translateButton = Tween<double>(
      begin: _fabHeight,
      end: -14.0,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Interval(
        0.0,
        0.75,
        curve: _curve,
      ),
    ));
    super.initState();
  }

  @override
  dispose() {
    _animationController.dispose();
    super.dispose();
  }

  animate() {
    if (!isOpened) {
      _animationController.forward();
    } else {
      _animationController.reverse();
    }
    isOpened = !isOpened;
  }

  Widget add() {
    return Container(
      child: FloatingActionButton(
        onPressed: null,
        tooltip: 'Add',
        child: Icon(Icons.add),
      ),
    );
  }

  Widget image() {
    return Container(
      child: FloatingActionButton(
        onPressed: null,
        tooltip: 'Image',
        child: Icon(Icons.image),
      ),
    );
  }

  Widget inbox() {
    return Container(
      child: FloatingActionButton(
        onPressed: null,
        tooltip: 'Inbox',
        child: Icon(Icons.inbox),
      ),
    );
  }

  Widget toggle() {
    return Container(
      child: FloatingActionButton(
        backgroundColor: _buttonColor.value,
        onPressed: animate,
        tooltip: 'Toggle',
        child: AnimatedIcon(
          icon: AnimatedIcons.menu_close,
          progress: _animateIcon,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Transform(
          transform: Matrix4.translationValues(
            0.0,
            _translateButton.value * 3.0,
            0.0,
          ),
          child: add(),
        ),
        Transform(
          transform: Matrix4.translationValues(
            0.0,
            _translateButton.value * 2.0,
            0.0,
          ),
          child: image(),
        ),
        Transform(
          transform: Matrix4.translationValues(
            0.0,
            _translateButton.value,
            0.0,
          ),
          child: inbox(),
        ),
        toggle(),
      ],
    );
  }
}

Voglio usare questo widget in Flutterlistview, che dovrebbe apparire dove ho cliccato, per esempio supponi che io abbia io IconButtonnegli ListViewelementi, quando ci clicco sopra, questo widget dovrebbe apparire nella posizione cliccata e Buttondovrebbe essereFloatingActionButton

Risposte

4 AnasMohammed Oct 29 2020 at 20:47

L'ho implementato usando Stacke AnimatedContainer.

  • usando Positionedin Stack, l'ho posizionato in basso. La ragione di ciò è allineare sia il Containerche FABnella stessa posizione quando è animato.
  • usando AnimatedContainer, ho creato una semplice animazione che cambia la sua altezza quando FABtocchiamo usando il valore bool.

(Aggiungo un contenitore in più nella colonna, si nasconderà dietro FAB e lo allineerà perfettamente, ma puoi aggiungere SizedBox o Container senza colore e mantenere le sue dimensioni come 54.0 alla fine, se non stai usando list.generate)

Prova questo su DartPad

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
            child: Container(
          width: 250,
          height: 250,
          color: Colors.white,
          child: YellowBird(),
        )),
      ),
    );
  }
}

class YellowBird extends StatefulWidget {
  const YellowBird({Key key}) : super(key: key);

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

class _YellowBirdState extends State<YellowBird> {
  bool animate = true;

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: AlignmentDirectional.topCenter,
      children: [
      Positioned(
        bottom: 0,
        child: AnimatedContainer(
            width: 54.0,
            decoration: BoxDecoration(
             color: Colors.redAccent,
             borderRadius: BorderRadius.all(Radius.circular(360))
            ),
            height: animate ? 56.0 : 250.0,
            duration: Duration(milliseconds: 300),
            child: animate
                ? Container()
                : Column(
                    children: List.generate(
                        4,
                        (i) => Expanded(
                                child: Container(
                              width: 50,
                              height: 50,
                              decoration: BoxDecoration(
                                color: Colors.white,
                                shape: BoxShape.circle,
                              ),
                           ),
                        ),
                     ),
                  ),
               ),
            ),
      Positioned(
          bottom: 0,
          child: FloatingActionButton(
              backgroundColor: Colors.grey,
          child: Icon(animate ? Icons.menu : Icons.close, size: 30),
              onPressed: () {
                setState(() {
                  animate = !animate;
                });
              })),
    ]);
  }
}

fammi sapere se funziona o c'è qualcosa da cambiare da questo.

mohandesR Nov 03 2020 at 03:24

ciao per favore guarda questa libreria ... https://pub.dev/packages/flutter_portal questo è il modo più semplice per creare una sovrapposizione in Flutter ...

PortalEntry(
  visible: isMenuVisible, //true Or False
  portalAnchor: Alignment.topLeft,
  childAnchor: Alignment.topRight,
  portal: TheMenuWidget, // option 1 + option 2 (White)
  child: MyButton, // show Menu Button (Grey) 
)