In this section, we will create the navigation bar for our home page by using the widgets RawMaterialButton, TextField, Icon, and CircleAvatar. We’ll also learn how the GestureDetector widget can be used to detect taps and run code when gestures are recognized.

Get Started

We’ll begin by making some modifications to the Scaffold widget.

Column(
  children: [
    RecentCourseCard(
      course: recentCourses[2],
    ),
  ],
),
Container(
  color: kBackgroundColor,
  child: Column(
		children: [
			RecentCourseCard(
				course: recentCourses[2],
			),
		],
	),
),
Scaffold(
  body: Container(
    color: kBackgroundColor,
    child: SafeArea(
      child: Column(
        children: [
          HomeScreenNavBar(),
          RecentCourseCard(
            course: recentCourses[2],
          ),
        ],
      ),
    ),
  ),
),

Create the Home Screen Navigation Bar

At the bottom of main.dart, type the shortcut stless to create a new stateless widget.

class HomeScreenNavBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
Column(
  children: [
    HomeScreenNavBar(),
    RecentCourseCard(
      course: recentCourses[2],
    ),
  ],
),

Configure the HomeScreenNavBar Constraints

Inside our HomeScreenNavBar widget, we need to arrange our widgets horizontally. The best widget for this type of layout is the Row widget.

return Row();
return Row(
	mainAxisAlignment: MainAxisAlignment.spaceBetween
);
return Padding(
  padding: EdgeInsets.all(20.0),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
  ),
);

Build the Sidebar Button

The first widget we will build in our navigation bar is the sidebar button. Add the children argument to the Row widget and inside the list, we’ll be using the RawMaterialButton widget.

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    RawMaterialButton(
      onPressed: () {
        print("Sidebar button pressed");
      },
      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
      highlightColor: Colors.transparent,
      splashColor: Colors.transparent,
      constraints: BoxConstraints(
        maxWidth: 40.0,
        maxHeight: 40.0,
      ),
      child: Container(
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(14.0),
          boxShadow: [
            BoxShadow(
              color: kShadowColor,
              offset: Offset(0, 12),
              blurRadius: 16.0,
            )
          ],
        ),
        child: Image.asset(
          'asset/icons/icon-sidebar.png',
          color: kPrimaryLabelColor,
        ),
        padding: EdgeInsets.symmetric(
          horizontal: 12.0,
          vertical: 14.0,
        ),
      ),
    ),
  ],
),

Extract the SidebarButton Widget

Before we add any more widgets to our navigation bar, it will be helpful to refactor a little bit by extracting the entire RawMaterialButton widget into its own separate widget.

Creating the Notification Button

The notification button will be created in the same Row widget after the SidebarButton widget. We’ll use a simply Icon widget to build this. Place the following code after the SidebarButton inside the list of row children.

Icon(
  Icons.notifications,
  color: kPrimaryLabelColor,
),

Creating the Profile Button

The profile button will be built using the CircleAvatar widget. It will be created right after the notification Icon widget that was just created. However, to avoid both the notification button and the profile button from being grouped so close together, we’ll need to add a SizedBox widget to provide some spacing between the two widgets. So inside the same list, type the following right after Icon.

SizedBox(
  width: 16.0,
),
CircleAvatar(
  radius: 18.0,
  backgroundImage: AssetImage('asset/images/profile.jpg'),
),

Create the SearchFieldWidget

At the bottom of main.dart, create a new stateless widget. We’ll call this SearchFieldWidget. You can do this by using the shortcut stless.

class SearchFieldWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

We’ll also need to add this widget to the Row widget right before the Icon widget and after the SidebarButton widget.

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    SidebarButton(),
    SearchFieldWidget(),
    Icon(
      Icons.notifications,
      color: kPrimaryLabelColor,
    ),
    SizedBox(
      width: 16.0,
    ),
    CircleAvatar(
      radius: 18.0,
      backgroundImage: AssetImage('asset/images/profile.jpg'),
    ),
  ],
),

Designing the SearchFieldWidget

The SearchFieldWidget is a creation of multiple widgets nested amongst each other. Some items to note here are such.

return Expanded(
  child: Padding(
    padding: EdgeInsets.only(left: 12.0, right: 33.0),
    child: Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(14.0),
        boxShadow: [
          BoxShadow(
            color: kShadowColor,
            offset: Offset(0, 12),
            blurRadius: 16.0,
          )
        ],
      ),
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 16.0),
        child: TextField(
          cursorColor: kPrimaryLabelColor,
          decoration: InputDecoration(
            icon: Icon(
              Icons.search,
              color: kPrimaryLabelColor,
              size: 20.0,
            ),
            border: InputBorder.none,
            hintText: "Search for courses",
            hintStyle: kSearchPlaceholderStyle,
          ),
          style: kSearchTextStyle,
          onChanged: (newText) {
            print(newText);
          },
        ),
      ),
    ),
  ),
);