首页 > 解决方案 > Flutter - 如何使用持久按钮创建底部侧边栏以打开和关闭它

问题描述

我想创建带有持久按钮的底部侧边栏来打开和关闭它,现在使用 ashowModalBottomSheet但我不知道如何将按钮附加到ModalBottomSheet

这就是我的应用程序现在所做的: 在此处输入图像描述

这就是我想要实现的目标:

在此处输入图像描述

标签: flutterdartbottom-sheet

解决方案


我希望我明白你的意思,尝试在 a 中使用这个类Stack并使其适应你的需要:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';

class CycleSideBar extends StatefulWidget {
  const CycleSideBar({Key? key}) : super(key: key);
  @override
  _CycleSideBarState createState() => _CycleSideBarState();
}

class _CycleSideBarState extends State<CycleSideBar>
    with SingleTickerProviderStateMixin<CycleSideBar> {
  AnimationController? _animationController;
  StreamController<bool>? isSideBarOpenedStreamController;
  Stream<bool>? isSideBarOpenedStream;
  StreamSink<bool>? isSideBarOpenedSink;
  final _animationDuration = const Duration(milliseconds: 400);

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

    _animationController =
        AnimationController(vsync: this, duration: _animationDuration);
    isSideBarOpenedStreamController = PublishSubject<bool>();
    isSideBarOpenedStream = isSideBarOpenedStreamController!.stream;
    isSideBarOpenedSink = isSideBarOpenedStreamController!.sink;
  }

  @override
  void dispose() {
    _animationController!.dispose();
    isSideBarOpenedStreamController!.close();
    isSideBarOpenedSink!.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var heightOfScreen = MediaQuery.of(context).size.height;
    List<Widget> children = [];
    return StreamBuilder<bool>(
      initialData: false,
      stream: isSideBarOpenedStream,
      builder: (context, isCycleSideBarOpenedAsync) {
        return AnimatedPositioned(
          duration: _animationDuration,
          top: isCycleSideBarOpenedAsync.data!
              ? heightOfScreen - 300
              : heightOfScreen - 113,
          left: 0,
          right: 0,
          bottom: 0,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              TextButton(
                onPressed: () => onIconPressed(),
                child: Text('Test'),
              ),
              SizedBox(
                height: 10,
              ),
              Expanded(
                child: Container(
                  color: Colors.white.withOpacity(0.4),
                  child: Wrap(
                    alignment: WrapAlignment.center,
                    spacing: 10,
                    runSpacing: 10,
                    children: _builItemsOfBottomSheet(children),
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  void onIconPressed() {
    final animationStatus = _animationController!.status;
    final isAnimationCompleted = animationStatus == AnimationStatus.completed;

    if (isAnimationCompleted) {
      isSideBarOpenedSink!.add(false);
      _animationController!.reverse();
    } else {
      isSideBarOpenedSink!.add(true);
      _animationController!.forward();
    }
  }

  List<Widget> _builItemsOfBottomSheet(List<Widget> children) {
    children.clear();
    for (int i = 0; i < 10; i++) {
      children.add(Container(color: Colors.green, child: Text('Text_$i')));
    }

    return children;
  }
}

我希望这是有帮助的


推荐阅读