Flutter AppBar PopupMenuButton. Want leading Icon with Pop and right-side Icon with Popup

6.5k Views Asked by At

--> Screenshot Image <-- Using Flutter for first project after weeks of learning through tutorials and other resources. Using AppBar with Leading Icon (left) and PopupMenuButton with icon (right). The popup menu works fine however would like to have a popup menu on the left/leading icon.

I've tried duplicating the code under the action widget on right however Flutter doesn't like it. I believe the leading icon is limited whereas the icon/right-side can handle more widgets/code.

import 'package:flutter/material.dart';
import 'package:paycheck_academy/fab_bottom_app_bar.dart';
import 'package:paycheck_academy/fab_with_icons.dart';
import 'package:paycheck_academy/layout.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or press Run > Flutter Hot Reload in IntelliJ). Notice that the
        // counter didn't reset back to zero; the application is not restarted.
        primarySwatch: Colors.blueGrey,
      ),
      home: new MyHomePage(title: 'Paycheck Academy'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  String _lastSelected = 'TAB: 0';

  void _selectedTab(int index) {
    setState(() {
      _lastSelected = 'TAB: $index';
    });
  }

  void _selectedFab(int index) {
    setState(() {
      _lastSelected = 'FAB: $index';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        //Can add leading icon/function if needed
        leading: Builder(
          builder: (BuildContext context) {
            return IconButton(
              icon: Icon(Icons.menu),
              onPressed: () {},
            );
          },
        ),
/*        Icon(
          Icons.exit_to_app,
        ),*/
        actions: <Widget>[
          PopupMenuButton(
            icon: Icon(Icons.account_box),
            tooltip: 'Account',
            itemBuilder: (context) => [
              PopupMenuItem(
                child: Text(
                  'Profile',
                  style: TextStyle(
                    color: Colors.blueGrey,
                  ),
                ),
              ),
              PopupMenuItem(
                child: Text(
                  'FAQ',
                  style: TextStyle(
                    color: Colors.blueGrey,
                  ),
                ),
              ),
              PopupMenuItem(
                child: Text(
                  'Website',
                  style: TextStyle(
                    color: Colors.blueGrey,
                  ),
                ),
              ),
              PopupMenuItem(
                child: Text(
                  'Logout',
                  style: TextStyle(
                    color: Colors.blueGrey,
                  ),
                ),
              ),
            ],
          ),
        ],
        title: Text(widget.title),
        textTheme: TextTheme(
          title: TextStyle(
            color: Colors.white,
            fontSize: 22.0,
          ),
        ),
        /*actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.account_box,
              color: Colors.white,
            ),
            onPressed: () {},
          ),
        ],*/
      ),
      body: Center(
        child: Text(
          _lastSelected,
          style: TextStyle(fontSize: 32.0),
        ),
      ),
      bottomNavigationBar: FABBottomAppBar(
        centerItemText: '',
        backgroundColor: Colors.blueGrey,
        color: Colors.white,
        selectedColor: Colors.yellowAccent,
        notchedShape: CircularNotchedRectangle(),
        onTabSelected: _selectedTab,
        items: [
          FABBottomAppBarItem(
            iconData: Icons.school,
            text: 'Academy',
          ),
          FABBottomAppBarItem(
            iconData: Icons.insert_chart,
            text: 'Reports',
          ),
          FABBottomAppBarItem(
            iconData: Icons.attach_money,
            text: 'Income',
          ),
          FABBottomAppBarItem(
            iconData: Icons.local_grocery_store,
            text: 'Expense',
          ),
        ],
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      floatingActionButton: _buildFab(
          context), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  Widget _buildFab(BuildContext context) {
    final icons = [
      Icons.attach_money,
      Icons.local_grocery_store,
    ];
    return AnchoredOverlay(
      showOverlay: true,
      overlayBuilder: (context, offset) {
        return CenterAbout(
          position: Offset(offset.dx, offset.dy - icons.length * 35.0),
          child: FabWithIcons(
            icons: icons,
            onIconTapped: _selectedFab,
          ),
        );
      },
      child: FloatingActionButton(
        onPressed: () {},
        tooltip: 'Increment',
        child: Icon(Icons.add),
        elevation: 2.0,
      ),
    );
  }
}
2

There are 2 best solutions below

0
On BEST ANSWER

enter image description here

 Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('PopupMenuButton (Stateless)'),
      actions: <Widget>[
        PopupMenuButton(
          onSelected: (value) {
            //print the selected option
            print(value);

            //Update the current choice.
            //However, this choice won't be updated in body section since it's a Stateless widget.
            choice = value.toString();
          },
          itemBuilder: (BuildContext context) {
            return NavLinks.values.map((link) {
              return PopupMenuItem(
                value: link,
                child: Text(displayString(link)),
              );
            }).toList();
          },
        ),
      ],
    ),
    body: Center(
      child: Text(
        //Print the current choice
        choice,
        style: TextStyle(fontSize: 30),
      ),
    ),
  );
}
0
On

So... I tried this out. And it seems like what you want.

  class CustomAppBar extends StatefulWidget implements PreferredSizeWidget{

  final double height;

  CustomAppBar({Key key,this.height}):super(key:key);

  Size get preferredSize => Size.fromHeight(height);

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

class _CustomAppBarState extends State<CustomAppBar> {

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          color: Colors.grey[300],
          child: Padding(
            padding: EdgeInsets.all(0),
            child: Container(
              color: Colors.red,
              padding: EdgeInsets.fromLTRB(5, 30, 5, 5),
              child: Row(children: [
                PopupMenuButton(
                  icon: Icon(Icons.view_list,color:Colors.white),
                  itemBuilder: (context) => [
                    PopupMenuItem(
                      child: Text("Is this"),
                    ),
                    PopupMenuItem(
                      child: Text("What"),
                    ),
                    PopupMenuItem(
                      child: Text("You Want?"),
                    ),
                  ],
            ),
                Expanded(
                  child: Container(
                    color: Colors.transparent,
                    child: Text("Hello",
                    style: TextStyle(
                      fontSize:20.0,
                      color:Colors.white,
                    ),),
                  ),
                ),
              ]),
            ),
          ),
        ),
      ],
    );
  }
}

And you can use this Class In replace to the AppBar().. ie:appBar: CustomAppBar(height:95.0),

This is how it look

And this is the pop up

Btw.. Im also new to flutter... so my code might be stupid a Little bit ...