IllegalFloatingActionButtonSizeException Floating action button must be a circle

Viewed 485

I'm getting the following error:

IllegalFloatingActionButtonSizeException: Floating action button must be a circle File "circular_notch_and_corner_clipper.dart", line 25, in CircularNotchedAndCorneredRectangleClipper.getClip File "proxy_box.dart", line 1314, in _RenderCustomClip._updateClip File "proxy_box.dart", line 1935, in RenderPhysicalShape.paint File "object.dart", line 2311, in RenderObject._paintWithContext File "object.dart", line 189, in PaintingContext.paintChild File "box.dart", line 2826, in RenderBoxContainerDefaultsMixin.defaultPaint File "custom_layout.dart", line 407, in RenderCustomMultiChildLayoutBox.paint File "object.dart", line 2311, in RenderObject._paintWithContext File "object.dart", line 189, in PaintingContext.paintChild File "proxy_box.dart", line 131, in RenderProxyBoxMixin.paint File "material.dart", line 555, in _RenderInkFeatures.paint File "object.dart", line 2311, in RenderObject._paintWithContext File "object.dart", line 189, in PaintingContext.paintChild File "proxy_box.dart", line 131, in RenderProxyBoxMixin.paint File "object.dart", line 396, in PaintingContext.pushLayer File "proxy_box.dart", line 1862, in RenderPhysicalModel.paint File "object.dart", line 2311, in RenderObject._paintWithContext File "object.dart", line 189, in PaintingContext.paintChild File "proxy_box.dart", line 131, in RenderProxyBoxMixin.paint File "object.dart", line 2311, in RenderObject._paintWithContext File "object.dart", line 189, in PaintingContext.paintChild File "proxy_box.dart", line 131, in RenderProxyBoxMixin.paint File "object.dart", line 2311, in RenderObject._paintWithContext File "object.dart", line 189, in PaintingContext.paintChild File "proxy_box.dart", line 131, in RenderProxyBoxMixin.paint File "object.dart", line 2311, in RenderObject._paintWithContext File "object.dart", line 140, in PaintingContext._repaintCompositedChild File "object.dart", line 100, in PaintingContext.repaintCompositedChild File "object.dart", line 978, in PipelineOwner.flushPaint File "binding.dart", line 438, in RendererBinding.drawFrame File "binding.dart", line 914, in WidgetsBinding.drawFrame File "binding.dart", line 302, in RendererBinding._handlePersistentFrameCallback File "binding.dart", line 1117, in SchedulerBinding._invokeFrameCallback File "binding.dart", line 1055, in SchedulerBinding.handleDrawFrame File "binding.dart", line 971, in SchedulerBinding._handleDrawFrame File "zone.dart", line 1190, in _rootRun File "zone.dart", line 1093, in _CustomZone.run File "zone.dart", line 997, in _CustomZone.runGuarded File "hooks.dart", line 251, in _invoke File "hooks.dart", line 209, in _drawFrame

I guess maybe it's related to the device type, but I'm not sure. Here one of the devices where I saw the error:

brand: "samsung", device: "crownlte", model: "SM-N960F"

The relevant code:

import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart';

AnimationController _animationController;
  Animation<double> animation;

  @override
  void initState() {
    _animationController = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );

    CurvedAnimation curve = CurvedAnimation(
      parent: _animationController,
      curve: Interval(
        0.5,
        1.0,
        curve: Curves.fastOutSlowIn,
      ),
    );

    animation = Tween<double>(
      begin: 0,
      end: 1,
    ).animate(curve);

    WidgetsBinding.instance.addPostFrameCallback(
      (_) {
        _handleInternetConnection();

        Future.delayed(
          Duration(seconds: 1),
          () {
            if (mounted) _animationController.forward();
          },
        );
      },
    );

    super.initState();
  }

...
floatingActionButton: (_currentIndex != 3 && showFAB)
            ? ScaleTransition(
                scale: animation,
                child: FloatingActionButton(
                  elevation: 8,
                  foregroundColor: Colors.white,
                  child: Icon(
                    _currentIndex == 0
                        ? Icons.edit
                        : Icons.face_retouching_natural,
                    size: 36,
                  ),
                  onPressed: () => _currentIndex == 0
                      ? NewStory.show(context, null)
                      : NewMood.show(context, null),
                ),
              )
            : null,
floatingActionButtonLocation:
              FloatingActionButtonLocation.centerDocked,
          bottomNavigationBar: AnimatedBottomNavigationBar(
            icons: allDestinations()
                .map((NavbarOption destination) => destination.icon)
                .toList(),
            activeColor: Colors.white,
            splashColor: Theme.of(context).primaryColor,
            activeIndex: _currentIndex,
            gapLocation: GapLocation.center,
            inactiveColor: Colors.white60,
            notchAndCornersAnimation: animation,
            backgroundColor: Theme.of(context).primaryColor,
            notchSmoothness: NotchSmoothness.softEdge,
            onTap: (index) => setState(() => _currentIndex = index),
          ),
        ),
2 Answers

Maybe the following reasons might be causing the error since you mentioned that it doesn't happen every time

Maybe, the scale transition beginning from 0 ( begin:0) is causing the error because when it is scaled to 0 it is no longer a circle. So changing the begins to a value that is approx. 0 might solve the error i.e. begin:0.00001.

OR

 WidgetsBinding.instance.addPostFrameCallback(
      (_) {
        _handleInternetConnection();

        Future.delayed(
          Duration(seconds: 1),
          () {
            if (mounted) _animationController.forward();
          },
        );
      },
    );

Solution:

  1. Setting begin to begin:0.00001

  2. Also, it's better to use implicit animation if you want a widget to animate as soon as it is built. I've modified the code to include implicit animation instead of explicit animation ( where forward() must be called explicitly to animate).

Try this example (Uses null safety)

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

/// This is the main application widget.
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _selectedIndex = 0;
  static const TextStyle optionStyle =
      TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
  static const List<Widget> _widgetOptions = <Widget>[
    Text(
      'Index 0: Home',
      style: optionStyle,
    ),
    Text(
      'Index 1: Business',
      style: optionStyle,
    ),
    Text(
      'Index 2: School',
      style: optionStyle,
    ),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      floatingActionButton: _selectedIndex == 0
          ? TweenAnimationBuilder<double>(
              tween: Tween<double>(
                begin: 0.00001,
                end: 1,
              ),
              curve: Interval(
                0.5,
                1.0,
                curve: Curves.fastOutSlowIn,
              ),
              duration: Duration(milliseconds: 700),
              builder: (_, double scaleValue, __) {
                return Transform.scale(
                    scale: scaleValue,
                    child: FloatingActionButton(
                      elevation: 8,
                      foregroundColor: Colors.white,
                      child: Icon(
                        Icons.face_retouching_natural,
                        size: 36,
                      ),
                      onPressed: () {
                        print("hi");
                      },
                    ));
              })
          : null,
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            label: 'Business',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            label: 'School',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

Firstly, try to run it using the latest version of the library and flutter. If it still exists, please tell me. I cannot reproduce it, so if you can do so, please give a minimal reproducible sample.

Secondly, about "I guess maybe it's related to the device type, but I'm not sure.", it is possibly not related to the device, since Flutter is cross-platform, and your code seems not to be related to native code.

Thirdly, try to use the "binary-search debug" technique. For example, try to remove all arguments from AnimatedBottomNavigationBar() and see whether it works. If so, add a few arguments and try again. If works again, add more arguments; otherwise remove some. By doing this you will see which argument causes the problem.

Related