Search code examples
flutterflutter-layoutflutter-animationflutter-appbar

Flutter: How to use animated icon in the AppBar - I want to use this animated icon instead of Animatedless Icon, in the appbar of flutter app


I want to use the animated icon in this AppBar, but can not be done because the animated icon have a stateful widget with "with TickerProviderStateMixin". If I move the whole scaffold to a stateful widget then the "onMenuTap" is not working. The main purpose of the Question is to use the animated icon in the Flutter AppBar.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../FreelanceTheme/AppStyleModeNotifier.dart';

class HomePage extends StatelessWidget with NavigationStates {
      final Function onMenuTap;
      const HomePage({Key key, this.onMenuTap}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        final appStyleMode = Provider.of<AppStyleModeNotifier>(context);
        return MaterialApp(
          home: Scaffold(
            backgroundColor: Color(0xffE5E5E5),
            appBar: AppBar(
              elevation: 0,
              backgroundColor: appStyleMode.appBarBackgroundColor,
              actions: <Widget>[
                Switch(
                  activeColor: Colors.orange,
                  value: appStyleMode.mode,
                  onChanged: (value) => appStyleMode.switchMode(),
                ),
              ],
              leading: IconButton(
                tooltip: 'App Settings',
                icon: Icon(
                  FontAwesomeIcons.bars,
                  color: Colors.white,
                ),
                onPressed: onMenuTap,
              ),
              centerTitle: true,
              title: Text(
                "Home",
                style: TextStyle(
                  color: Colors.white,
                ),
              ),
            ),
            body: FreelancingHomePage(),
          ),
        );
      }
    }

I want to replace this IconButton with the animated icon in the appbar.

leading: IconButton(
                tooltip: 'App Settings',
                icon: Icon(
                  FontAwesomeIcons.bars,
                  color: Colors.white,
                ),
                onPressed: onMenuTap,
              ),

Following is the code for the animated icon. I want to use this animated icon in the above appBar.

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {

 AnimationController _animationIconController1,
 bool isarrowmenu = false;


@override
  void initState() {
    super.initState();
    _animationIconController1 = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 750),
      reverseDuration: Duration(milliseconds: 750),
    );
 }

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(


GestureDetector(
              onTap: () {
                setState(() {
                  isarrowmenu
                      ? _animationIconController1.reverse()
                      : _animationIconController1.forward();
                  isarrowmenu = !isarrowmenu;
                });
              },
              child: ClipOval(
                child: Container(
                  decoration: BoxDecoration(
                    border: Border.all(
                      width: 2.5,
                      color: Colors.green,
                    ),
                    borderRadius: BorderRadius.all(
                      Radius.circular(50.0),
                    ),
                  ),
                  width: 75,
                  height: 75,
                  child: Center(
                    child: AnimatedIcon(
                      icon: AnimatedIcons.arrow_menu,
                      progress: _animationIconController1,
                      color: Colors.red,
                      size: 60,
                    ),
                  ),
                ),
              ),
            ),
     ),
   );
 }

Solution

  • You can copy paste run full code below
    Step 1: You can make this animated icon with StatefulWidget that have VoidCallback onMenuTap

    class CustomIcon extends StatefulWidget {
      VoidCallback onMenuTap;
    
      CustomIcon({Key key, this.onMenuTap}) : super(key: key);
      @override
      _CustomIconState createState() => _CustomIconState();
    }
    
    class _CustomIconState extends State<CustomIcon> with TickerProviderStateMixin {
      AnimationController _animationIconController1;
    

    Step 2: In leading, you can use CustomIcon and pass onMenuTap

    home: HomePage(
            onMenuTap: () {
              print("hi");
            },
          ),
    ...   
    leading: CustomIcon(
                onMenuTap: () {
                  onMenuTap();
                },
              ),
    

    working demo

    enter image description here

    output of working demo

    I/flutter (25195): hi
    I/flutter (25195): hi
    

    full code

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: HomePage(
            onMenuTap: () {
              print("hi");
            },
          ),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      final Function onMenuTap;
      const HomePage({Key key, this.onMenuTap}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        //final appStyleMode = Provider.of<AppStyleModeNotifier>(context);
        return MaterialApp(
          home: Scaffold(
            backgroundColor: Color(0xffE5E5E5),
            appBar: AppBar(
              elevation: 0,
              backgroundColor: Colors.blue,
              actions: <Widget>[
                /* Switch(
                  activeColor: Colors.orange,
                  value: appStyleMode.mode,
                  onChanged: (value) => appStyleMode.switchMode(),
                ),*/
              ],
              leading: CustomIcon(
                onMenuTap: () {
                  onMenuTap();
                },
              ),
              centerTitle: true,
              title: Text(
                "Home",
                style: TextStyle(
                  color: Colors.white,
                ),
              ),
            ),
            body: Text("FreelancingHomePage()"),
          ),
        );
      }
    }
    
    class CustomIcon extends StatefulWidget {
      VoidCallback onMenuTap;
    
      CustomIcon({Key key, this.onMenuTap}) : super(key: key);
      @override
      _CustomIconState createState() => _CustomIconState();
    }
    
    class _CustomIconState extends State<CustomIcon> with TickerProviderStateMixin {
      AnimationController _animationIconController1;
      bool isarrowmenu = false;
    
      @override
      void initState() {
        super.initState();
        _animationIconController1 = AnimationController(
          vsync: this,
          duration: Duration(milliseconds: 750),
          reverseDuration: Duration(milliseconds: 750),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: () {
            setState(() {
              isarrowmenu
                  ? _animationIconController1.reverse()
                  : _animationIconController1.forward();
              isarrowmenu = !isarrowmenu;
    
              if (widget.onMenuTap != null) {
                widget.onMenuTap();
              }
            });
          },
          child: ClipOval(
            child: Container(
              decoration: BoxDecoration(
                border: Border.all(
                  width: 2.5,
                  color: Colors.green,
                ),
                borderRadius: BorderRadius.all(
                  Radius.circular(50.0),
                ),
              ),
              width: 75,
              height: 75,
              child: Center(
                child: AnimatedIcon(
                  icon: AnimatedIcons.arrow_menu,
                  progress: _animationIconController1,
                  color: Colors.red,
                  size: 60,
                ),
              ),
            ),
          ),
        );
      }
    }