# Widgets 14 | PopupMenuButton

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIy-TxdzY0UQbxR926%2F-LXIy1w8-C5h-hlviEyH%2Fpopup-menu-button-10.png?alt=media\&token=94b8c466-aead-4090-bf72-dd979f508206)

## Before Start

Before starting our tutorial, we should create a page to contain our code.

```dart
import "package:flutter/material.dart";
import 'package:flutter_widgets/const/_const.dart';

class PopupMenuButtonPage extends StatefulWidget {
  @override
  _PopupMenuButtonState createState() => _PopupMenuButtonState();
}

class _PopupMenuButtonState extends State<PopupMenuButtonPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(PageName.POPUP_MENU_BUTTON),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            //our code.
            SizedBox(height: 600)
          ],
        ),
      ),
    );
  }
}
```

This is an empty page with a title.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIPtlKl-lhNNNMx6Um%2Fpopup-menu-button-01.png?alt=media\&token=3cc8a79a-9af4-40dd-9f3f-caa8e59ab115)

## Simple Use

The `PopupMenuButton` is similar with the `DropdownButton`, but has a bit different with it. The `PopupMenuButton` shows the menu but do not change the current button,you can do more things than the `DropdownButton`. So let's look at an example.

```dart
Widget _simplePopup() => PopupMenuButton<int>(
          itemBuilder: (context) => [
                PopupMenuItem(
                  value: 1,
                  child: Text("First"),
                ),
                PopupMenuItem(
                  value: 2,
                  child: Text("Second"),
                ),
              ],
        );
```

It will show three points in the picture. When you click it, it will show you a menu to choose.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXISbhHqzQecFFNJ0aD%2Fpopup-menu-button-02.png?alt=media\&token=52e77ef0-dab9-416d-955e-8bb656625d2d)

## Constructor

Let's look at its constructor for more use.

```dart
PopupMenuButton({
    Key key,
    @required this.itemBuilder,
    this.initialValue,
    this.onSelected,
    this.onCanceled,
    this.tooltip,
    this.elevation = 8.0,
    this.padding = const EdgeInsets.all(8.0),
    this.child,
    this.icon,
    this.offset = Offset.zero,
  }) 
```

The constructor has some parameters we have used them before, but some are not, so let's use them one by one.

## itemBuilder

This parameter defines as the blow.

```dart
  final PopupMenuItemBuilder<T> itemBuilder;
```

If you just look at this, you may do not know how to use it. You should look at the detail of the builder.

```dart
typedef PopupMenuItemBuilder<T> = List<PopupMenuEntry<T>> Function(BuildContext context);
```

It is a function and should return list with a type of the `PopupMenuEntry`. It is an abstract class, so we should use its subclasses. The relationship of the extends is below.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIXFup8S0El_h4JqAn%2Fpopup-menu-button-03.png?alt=media\&token=b538acd5-30f0-4625-8286-6f6a62b846d1)

So we can add the three classes to the list.So let's use them at the same time.

```dart
  Widget _threeItemPopup() => PopupMenuButton(
          itemBuilder: (context) {
            var list = List<PopupMenuEntry<Object>>();
            list.add(
              PopupMenuItem(
                child: Text("Setting Language"),
                value: 1,
              ),
            );
            list.add(
              PopupMenuDivider(
                height: 10,
              ),
            );
            list.add(
              CheckedPopupMenuItem(
                child: Text(
                  "English",
                  style: TextStyle(color: TEXT_BLACK),
                ),
                value: 2,
                checked: true,
              ),
            );
            return list;
          },
          icon: Icon(
            Icons.settings,
            size: 50,
            color: Colors.white,
          ),
        );
```

It will show as follows. When you click the button with a setting icon, it will show the right part, the upper item is the `PopupMenuItem`, the middle line the `PopupMenuDivider`, the bottom one is the `CheckedPopupMenuItem`.&#x20;

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIay3m5NvVr5EDWmMh%2Fpopup-menu-button-04.png?alt=media\&token=edcd14a2-8d50-4d46-80f0-f65993e482cc)

## onSelected

In this part, I will give you an example as below.

```dart
  Widget _selectPopup() => PopupMenuButton<int>(
          itemBuilder: (context) => [
                PopupMenuItem(
                  value: 1,
                  child: Text("First"),
                ),
                PopupMenuItem(
                  value: 2,
                  child: Text("Second"),
                ),
              ],
          initialValue: 2,
          onCanceled: () {
            print("You have canceled the menu.");
          },
          onSelected: (value) {
            print("value:$value");
          },
          icon: Icon(Icons.list),
        );
```

The **`initialValue`** will highlight the item with a grey background when showing the menu. The **`onCanceled`** is the function that will be called when you click the area that out of the menu.The **`onSelected`** is also a function with a value parameter that is the same as the value of the `PopupMenuItem`. The **`icon`** shows our button for us to click. The result is below.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIkGn5QXT96IpovNHO%2Fpopup-menu-button-05.png?alt=media\&token=a7faabbd-22f9-4c93-b915-351deed48563)

When you click the item of the menu or other areas that outside of the menu. It will print in the console like this.

```dart
I/flutter ( 5472): value:1
I/flutter ( 5472): You have canceled the menu.
```

## padding

This is very similar to us, so I just give an example to show the effect and see which part will change.&#x20;

```dart
   Widget _paddingPopup() => PopupMenuButton<int>(
          itemBuilder: (context) => [
                PopupMenuItem(
                  value: 1,
                  child: Text(
                    "English",
                    style:
                        TextStyle(color: PURPLE, fontWeight: FontWeight.w700),
                  ),
                ),
                PopupMenuItem(
                  value: 2,
                  child: Text(
                    "Chinese",
                    style:
                        TextStyle(color: PURPLE, fontWeight: FontWeight.w700),
                  ),
                ),
              ],
          elevation: 4,
          padding: EdgeInsets.symmetric(horizontal: 50),
        );
```

The `elevation` controls the shadow of the menu. The `padding` sets the distance of the button.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIn8nPnKAsfyoklipJ%2Fpopup-menu-button-06.png?alt=media\&token=e62281fc-15f9-4cf1-bb16-1aa1eb84ed5e)

## child&#x20;

This parameter will draw a widget for the button, but you should know, you can only choose either `child` or `icon`, do not use both of them.

```dart
  Widget _childPopup() => PopupMenuButton<int>(
          itemBuilder: (context) => [
                PopupMenuItem(
                  value: 1,
                  child: Text(
                    "Earth",
                    style: TextStyle(
                        color: TEXT_BLACK, fontWeight: FontWeight.w700),
                  ),
                ),
                PopupMenuItem(
                  value: 2,
                  child: Text(
                    "Moon",
                    style: TextStyle(
                        color: TEXT_BLACK, fontWeight: FontWeight.w700),
                  ),
                ),
                PopupMenuItem(
                  value: 3,
                  child: Text(
                    "Sun",
                    style: TextStyle(
                        color: TEXT_BLACK, fontWeight: FontWeight.w700),
                  ),
                ),
              ],
          child: Container(
            height: 50,
            width: 200,
            decoration: ShapeDecoration(
              color: GREEN,
              shape: StadiumBorder(
                side: BorderSide(color: TEXT_BLACK, width: 2),
              ),
            ),
            child: Icon(Icons.airplanemode_active),
          ),
        );
```

It will show as follows. The button will show our custom shape.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIpZCBObW8jJeJZAv3%2Fpopup-menu-button-07.png?alt=media\&token=92980860-ff44-41bc-8977-cdd66e766894)

## offset

This can control the location of the menu. So you should set this parameter to show your menu in the fit position. Let's see if we just set it to the `Offset(0,100)`, which position it will be.

```dart
Widget _offsetPopup() => PopupMenuButton<int>(
          itemBuilder: (context) => [
                PopupMenuItem(
                  value: 1,
                  child: Text(
                    "Flutter Open",
                    style: TextStyle(
                        color: TEXT_BLACK, fontWeight: FontWeight.w700),
                  ),
                ),
                PopupMenuItem(
                  value: 2,
                  child: Text(
                    "Flutter Tutorial",
                    style: TextStyle(
                        color: TEXT_BLACK, fontWeight: FontWeight.w700),
                  ),
                ),
              ],
          icon: Icon(Icons.library_add),
          offset: Offset(0, 100),
        );
```

It will show like this.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIu6GfpcDibx8wDvLW%2Fpopup-menu-button-08.png?alt=media\&token=66713d60-cd85-442a-8cdf-6f92a5e8dfbf)

If you don't set the offset, it will use the default value `Offset.zero`.It will show as below.

![](https://3262132263-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LW5X4rCYpodwj4P1c8s%2F-LXIOo1WFnTrCjFHg0Up%2F-LXIutxxfNzF8EkiGlkv%2Fpopup-menu-button-09.png?alt=media\&token=b9e3b5ed-d6ce-43f3-8012-c29fb441cde3)

## Conclusion

In this tutorial, we have learned many parameters of the `PopupMenuButton`. A bit difficult one is the `itemBuilder`, it isn't very obvious to a newer, it is a function that return list. The others will be easy to understand.&#x20;

Thanks for your reading!

The end.

#### Whole code in [GitHub](https://github.com/FlutterOpen/flutter-widgets-examples),star to support. <a href="#whole-code-in-github-star-to-support" id="whole-code-in-github-star-to-support"></a>

| Facebook Page                                         | Twitter                                 | GitHub                             | Medium                                        |
| ----------------------------------------------------- | --------------------------------------- | ---------------------------------- | --------------------------------------------- |
| [Flutter Open ](https://www.facebook.com/flutteropen) | [NieBin](https://twitter.com/niebin_gg) | [NieBin](https://github.com/nb312) | [FlutterOpen](https://medium.com/flutteropen) |
