Starting with Flutter: Fancy Lateral Menu
Tags: flutter, beginners, tutorial, dart
Published: 2021-06-16 15:02:09

Remember our lateral menu from this article? Yes, this one:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpztqxlq9y61xkh8oh93.png)

Pretty ugly isn't it? Let's make it fancier!

## 

## Center that list

Let's start by removing one of the most limiting features, or, at least, change it: the list. We'll change it to a Column and add the list as a child. 

```dart
endDrawer: Container(
        width: 200,
        color: Colors.white,
        child: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ListView.builder(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              itemCount: 4,
              itemBuilder: (context, index) {
                return Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: GestureDetector(
                    onTap: () {
                      Navigator.pop(context);
                      setState(() {
                        item = index;
                      });
                    },
                    child: Text('Item $index')
                  ),
                );
              },
            ),
          ],
        ),
      ),
```

 

The list is now a child of the column, also we needed to set column's height and set the list as `shrinkWrap` (or the list would not render properly) and block it's scrollable behavior. We are also centering our elements to achieve a cleaner look.

 

## Round it up

Let's now round our ugly squared white menu by wrapping our `Container` into a ClipRRect and let's give our menu some lovely curves!

```dart
      endDrawer: ClipRRect(
        borderRadius: BorderRadius.only(topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)),
        child: Container(
          width: 200,
          color: Colors.white,
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k4oq1l2ggc61eqjvi1i0.png)

Our menu now looks like this:


Half work done, let's get to the meaty part now!

## 

## Better items

Let's set a new look for our items, and let's show which one is clicked.

Keeping the "rounded" tradition of the menu we will give all our buttons a **new background** using the `ClipRRect` widget and a nice red color. We are adding a bit of complexity to our list item so we'll make brand new `StatelessWidget` with a calling function to maintain the page control on the main widget:

```dart
ListView.builder(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                itemCount: 4,
                itemBuilder: (context, index) {
                  return ListItem(
                    title: 'Item $index',
                    onClick: () {
                      Navigator.pop(context);
                      setState(() {
                        item = index;
                      });
                    },
                  );
                },
              ),


//That's our item
class ListItem extends StatelessWidget {
  final String title;
  final VoidCallback onClick;

  const ListItem({Key key, this.title, this.onClick}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8, left: 8),
      child: GestureDetector(
        onTap: () => onClick(),
        child: ClipRRect(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(30), bottomLeft: Radius.circular(30)),
          child: Container(
            color: Colors.red.shade500,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                title,
                style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 14),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
```

 

The final effect will be pretty nice:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ddldkq86bvo7xzxgfnb.png)

Now we want to show one item different from all others by setting it as "selected", so we'll add a "selected" property which will tell our item to have an orange background instead of a red one:

```dart
//How the new value is set:
                  return ListItem(
                    title: 'Item $index',
                    selected: index == item,
                    //Rest of the item...

/**The list item:**/
final bool selected;

child: ClipRRect(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(30), bottomLeft: Radius.circular(30)),
          child: Container(
            color: selected ? Colors.orangeAccent : Colors.red.shade500,
            child: Padding(
            //Rest of the item...
```

 

## Click effects

Last, but not least, we will add a click effect to our item by using the `CupertinoButton` widget. Again, we'll use a **custom widget** with a `CupertinoButton` inside. We'll need to set the `minSize` to 0 in order to let the button be as big as the child.

```dart
class TappableWidget extends StatelessWidget {
  final Widget child;
  final VoidCallback onTap;

  const TappableWidget({
    Key key,
    this.onTap,
    this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CupertinoButton(
        minSize: 0,
        padding: EdgeInsets.zero,
        onPressed: onTap,
        child: child
    );
  }
}
```

 

Our `ListItem` widget will look like this:

```dart
class ListItem extends StatelessWidget {
  final String title;
  final VoidCallback onClick;
  final bool selected;

  const ListItem({Key key, this.title, this.onClick, this.selected}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TappableWidget(
      onTap: () => onClick(),
      child: Padding(
        padding: const EdgeInsets.only(bottom: 8, left: 8),
        child: ClipRRect(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(30), bottomLeft: Radius.circular(30)),
          child: Container(
            width: MediaQuery.of(context).size.width,
            color: selected ? Colors.orangeAccent : Colors.red.shade500,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                title,
                style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                    fontSize: 14
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
```


The end result will be like this, with a nice fading effect while clicking:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqpn7xbqqql36ajk2oia.png)

## Way better now!

Our menu has a way better look than before, and it was relatively easy to do, don't you think? You can customize your menu as you wish, but adding new animations or behaviors will require a **complete change of code**. We will save it for another time. Stay tuned!