Flutter сделать простое меню Facebook

Oct 27 2020

В Flutterя пытаюсь сделать простое Facebookменю, в ниже скриншоте мы номер один виджет , и когда я нажимаю на том, что виджет , который находится ниже текущего виджета, должен быть изменен и расти и показывать еще иконки в том , что

этот ниже код, который я представил, справочник работает нормально, но у него нет фонового контейнера

в ссылке Columnиспользовалась ссылка, и я изменил ее на Stackи работает неправильно

Справка

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(),
      ],
    );
  }
}

Я хочу использовать этот виджет в Flutterсписке, который должен появиться там, где я щелкнул, например, вы полагаете, что у меня есть я IconButtonв ListViewэлементах, когда я нажимаю на него, этот виджет должен отображаться в выбранной позиции и Buttonдолжен бытьFloatingActionButton

Ответы

4 AnasMohammed Oct 29 2020 at 20:47

Я реализовал это с помощью Stackи AnimatedContainer.

  • используя Positionedin Stack, я поместил его внизу. Причина этого в том, чтобы выровнять Containerи FABв одном и том же положении при его анимации.
  • Используя AnimatedContainer, я сделал простую анимацию, которая меняет свою высоту, когда мы нажимаем на FABзначение bool.

(Я добавляю один дополнительный контейнер в столбец, он будет скрываться за FAB, а также идеально выровнять его, но вы можете добавить SizedBox или контейнер без цвета и, наконец, сохранить его размер 54.0, если вы не используете list.generate)

Попробуйте это на 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;
                });
              })),
    ]);
  }
}

дайте мне знать, если это сработает или они что-то изменит.

mohandesR Nov 03 2020 at 03:24

привет, пожалуйста, посмотрите эту библиотеку ... https://pub.dev/packages/flutter_portal это самый простой способ создать оверлей во 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) 
)