如何删除浮动操作按钮的右边距?

问题描述 投票:0回答:2

我将 FAB 实现为可扩展的,当单击 FAB 时,带有一点黑色覆盖。 我的问题是脚手架中有右边距,而我的叠加层没有填充整个视图。

如何删除右边距?

它的样子是这样的:

enter image description here

这是我的脚手架代码:

return Scaffold(
        resizeToAvoidBottomInset: true,
        floatingActionButton: !isSearchBarVisible ? SizedBox.expand(
          child: ExpandableFab(
            //key: _key,
            distance: size.height * 0.09,
            children: [
              /* not needed to show problem */
            ],
          ),
        ) : null,
        body: /* some body */

这是 ExpandableFab 类

class ExpandableFab extends StatefulWidget {
  const ExpandableFab({
    Key? key,
    this.initialOpen,
    required this.distance,
    required this.children,
  }) : super(key: key);

  final bool? initialOpen;
  final double distance;
  final List<Widget> children;

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

class _ExpandableFabState extends State<ExpandableFab>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  Animation<double>? _expandAnimation;
  bool _open = false;

  @override
  void initState() {
    super.initState();
    _open = widget.initialOpen ?? false;
    _controller = AnimationController(
      value: _open ? 1.0 : 0.0,
      duration: const Duration(milliseconds: 300),
      vsync: this,
    );
    _expandAnimation = CurvedAnimation(
      curve: Curves.fastOutSlowIn,
      reverseCurve: Curves.easeOutQuad,
      parent: _controller,
    );
  }

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

  void _toggle() {
    setState(() {
      _open = !_open;
      if (_open) {
        _controller.forward();
      } else {
        _controller.reverse();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return GestureDetector(
      onTap: () => _toggle(),
      child: Stack(
        alignment: Alignment.bottomRight,
        clipBehavior: Clip.none,
        children: [
            IgnorePointer(
              ignoring: !_open,
              child: TweenAnimationBuilder<double>(
                tween: Tween<double>(begin: 0.0, end: _open ? 1.0 : 0.0),
                duration: Duration(milliseconds: 500),
                curve: Curves.easeInOut,
                builder: (_, value, child) {
                  if (value < 0.001) {
                    return child!;
                  }
                  return BackdropFilter(
                    filter: ImageFilter.blur(sigmaX: value, sigmaY: value),
                    child: child,
                  );
                },
                child: Container(color: Colors.transparent),
              ),
            ),
            IgnorePointer(
              ignoring: !_open,
              child: AnimatedOpacity(
                duration: Duration(milliseconds: 500),
                opacity: _open ? 1 : 0,
                curve: Curves.easeInOut,
                child: Container(
                  color: Colors.black12,
                ),
              ),
            ),
          Transform.translate(
            offset: Offset(0, 0),
            child: Stack(
              alignment: Alignment.bottomRight,
              children: [
                Positioned(
                    bottom: size.height * 0.14,
                    child: _buildTapToCloseFab(size)
                ),
                Positioned(
                    bottom: size.height * 0.14,
                    child: _buildTapToOpenFab(size)
                ),
                ..._buildExpandingActionButtons(),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildTapToCloseFab(Size size) {
    return SizedBox(
      width: 56.0,
      height: 56.0,
      child: Center(
        child: Material(
          shape: const CircleBorder(),
          clipBehavior: Clip.antiAlias,
          elevation: 4.0,
          child: InkWell(
            onTap: _toggle,
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Icon(
                Icons.close,
                color: Theme.of(context).primaryColor,
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildTapToOpenFab(Size size) {
    return IgnorePointer(
      ignoring: _open,
      child: AnimatedContainer(
        transformAlignment: Alignment.center,
        transform: Matrix4.diagonal3Values(
          _open ? 0.7 : 1.0,
          _open ? 0.7 : 1.0,
          1.0,
        ),
        duration: const Duration(milliseconds: 250),
        curve: const Interval(0.0, 0.5, curve: Curves.easeOut),
        child: AnimatedOpacity(
          opacity: _open ? 0.0 : 1.0,
          curve: const Interval(0.25, 1.0, curve: Curves.easeInOut),
          duration: const Duration(milliseconds: 250),
          child: FloatingActionButton(
            onPressed: _toggle,
            child: Icon(
                Icons.add,
            ),
          ),
        ),
      ),
    );
  }

  List<Widget> _buildExpandingActionButtons() {
    final children = <Widget>[];
    final count = widget.children.length;
    final step = 90.0 / (count - 1);
    var dist;
    for (var i = 0, angleInDegrees = 0.0;
        i < count;
        i++, angleInDegrees += step) {
      if (i == 0) {
        dist = (widget.distance) * (i + 1);
      }
      else {
        dist = (widget.distance) * (i + 1);
      }
      children.add(
        _ExpandingActionButton(
          directionInDegrees: 90,
          maxDistance: dist,
          progress: _expandAnimation,
          child: widget.children[i],
        ),
      );
    }
    return children;
  }
}

class _ExpandingActionButton extends StatelessWidget {
  const _ExpandingActionButton({
    Key? key,
    required this.directionInDegrees,
    required this.maxDistance,
    required this.progress,
    required this.child,
  }) : super(key: key);

  final double directionInDegrees;
  final double maxDistance;
  final Animation<double>? progress;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return AnimatedBuilder(
      animation: progress!,
      builder: (BuildContext context, Widget? child) {
        final offset = Offset.fromDirection(
          directionInDegrees * (math.pi / 180.0),
          progress!.value * maxDistance,
        );
        return Positioned(
          right: 4.0 + offset.dx,
          bottom: (size.height * 0.14) + 4.0 + offset.dy,
          child: Transform.rotate(
            angle: (1.0 - progress!.value) * math.pi / 2,
            child: child,
          ),
        );
      },
      child: FadeTransition(
        opacity: progress!,
        child: child,
      ),
    );
  }
}

主要是 Flutter 教程中的代码:https://docs.flutter.dev/cookbook/effects/expandable-fab,有一些小的更改,例如 FAB 展开时垂直展开或覆盖。

flutter dart flutter-layout
2个回答
0
投票

使用这个结构:

    Scaffold(
    resizeToAvoidBottomInset: true,
    floatingActionButton: !isSearchBarVisible ? Padding(
      padding: const EdgeInsets.all(8.0),
      child: SizedBox.expand(
        child: ExpandableFab(
          //key: _key,
          distance: size.height * 0.09,
          children: [
            /* not needed to show problem */
          ],
        ),
      ),
    ) : null,
    body:

0
投票

您可以使用

Stack
小部件,请参阅更多信息 Stack Widget 文档

© www.soinside.com 2019 - 2024. All rights reserved.