Building a Hotel Booking app and looking for inspiration? Look no further, we will build two screens of a super clean hotel booking app using Flutter.

Last time on Reddit someone said that there are too many flutter UI tutorials and we should focus more on functionalities.

I personally believe that in order to attract beginners you have to show them fancy UIs and give them a starter code that they can learn from and improve.

I believe that everyone should share his knowledge if I have a talent creating UIs in flutter and I enjoy writing tutorials why should I stop? Especially that it is beneficial to a lot of people!

Obviously I mean no offense towards anyone. And I’d love to hear your opinion down in the comment section 🙂

After making things clear, let’s get started.

Download the project source code: https://github.com/cybdom/hotel_booking_ui

Donate to keep me posting: https://www.buymeacoffee.com/bi3cp0Zk5

Hotel booking UI: Home Screen:

Let’s begin by making the background, as you can see our Scaffold has 3 different shades of blue, you can’t achieve that buy just changing the backgroundColor of your Scaffold so here is what you have to do:

First, set your Scaffold background color:

backgroundColor: Color(0xff2446a6),

Then in a Stack create this child:

Positioned( left: 0, right: 0, top: 0, height: MediaQuery.of(context).size.height / 3, child: Row( children: [ Flexible( flex: 3, child: Container( color: Color(0xff4169d8), ), ), Flexible( flex: 1, child: Container( color: Color(0xff3a5fc8), ), ), ], ), ),

Now that we are done with the background let’s get into the profile container.

ClipRRect( borderRadius: BorderRadius.circular(15.0), child: Container( decoration: BoxDecoration( color: Colors.white, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: 15.0, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 15.0), child: Row( children: [ ClipRRect( borderRadius: BorderRadius.circular(5), child: Image.network( User.profilePicture, fit: BoxFit.cover, height: 35, width: 35, ), ), SizedBox( width: 15.0, ), Text( "${User.fullname}", style: Theme.of(context) .textTheme .headline .apply( color: MyColors.darkBlue, fontWeightDelta: 2), ), Spacer(), IconButton( icon: Icon( Icons.menu, color: MyColors.red, ), onPressed: () {}, ) ], ), ), SizedBox( height: 15.0, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 15.0), child: RichText( text: TextSpan( children: [ TextSpan( text: "3191", style: Theme.of(context) .textTheme .headline .apply( color: MyColors.darkBlue, fontWeightDelta: 2), ), TextSpan( text: "Travelers points", style: Theme.of(context) .textTheme .body2 .apply(color: MyColors.darkBlue), ) ], ), ), ), SizedBox( height: 15.0, ), Container( padding: const EdgeInsets.all(25.0), color: MyColors.red, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Align( alignment: Alignment.center, child: Text( "My next trip", style: Theme.of(context) .textTheme .headline .apply(color: Colors.white), ), ), Spacer(), Text( "28", style: Theme.of(context) .textTheme .headline .apply(color: Colors.white), ), Text( "Nov", style: Theme.of(context) .textTheme .body1 .apply(color: Colors.white), ) ], ), ) ], ), ), ),

You begin with a ClipRRect in order to get that circular border-radius, then inside a white Container, you create a Column that will hold a Row that shows your user’s profile picture, user name, and an IconButton. Below that there is a Rich text that shows how many points your user has earned. Last but not least is a Red Container that shows the date of your user’s next booking.

The goal of this app is to sell bookings to your clients, that’s why you need to make sure to display it in the most attractive way. Take a look at how I did it in this code:

GestureDetector( onTap: () => Navigator.push( context, MaterialPageRoute( builder: (ctx) => DetailsScreen(id: i), ), ), child: Container( width: 150, margin: const EdgeInsets.symmetric(horizontal: 11.0), child: ClipRRect( borderRadius: BorderRadius.circular(15.0), child: Stack( children: [ Positioned.fill( child: Image.network( destinationsList[i].imageUrl, fit: BoxFit.cover, ), ), Positioned( bottom: 0, left: 0, right: 0, child: Container( padding: EdgeInsets.symmetric(horizontal: 9.0, vertical: 5.0), decoration: BoxDecoration( color: MyColors.lighterBlue, borderRadius: BorderRadius.only( topRight: Radius.circular(15), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${destinationsList[i].placeName}", style: TextStyle( fontSize: 17, fontWeight: FontWeight.bold, color: Colors.white)), Text( "${destinationsList[i].date}", style: Theme.of(context) .textTheme .subtitle .apply(color: Colors.white), ), ], ), ), ) ], ), ), ), );

You start with the most important part which is handling the user tap using a GestureDetector. After that just like in the profile container use a ClipRRect to add the border-radius.

Instead of using a Column that will leave some empty space when you add a border-radius to the bottom container it is better to use a Stack that will ensure your Image takes the full space using Positioned.fill.

To finish up with the home screen, here is the bottom navigation bar which is just a Stateful Widget that returns a Row of MyBottomNavBarItem widgets. Using a stateful widget allows you to know which button is active.

Here is the code of MyBottomNavBarItem:

GestureDetector( onTap: function, child: Container( padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 9.0), decoration: BoxDecoration( color: active == id ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(25.0), ), child: Row( children: [ Icon( icon, color: active == id ? MyColors.darkBlue : Colors.white, ), SizedBox(width: 5), active == id ? Text( "$text", style: TextStyle( color: MyColors.darkBlue, fontWeight: FontWeight.bold), ) : Container() ], ), ), );

Hotel booking UI: Details Screen:

In this elegant UI, all the controls are on the right side, all the info is in the center, for that you can use a Row.

The hotel image here sits in a Stack and takes all the available space. At the top left corner, we have an IconButton that allows going back to the home screen. At the bottom, there is a Container with a LinearGradient decoration that gives that fading effect.

Now below the image, you can see all the info such as:

the hotel name the city name the booking date price and how many days are left before the trip.

Going back to the controls they are pretty simple as you can see, a column of Icon buttons for the first three buttons. Then a Red Container:

Container( decoration: BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(45), ), color: MyColors.red, ), child: Transform.rotate( angle: -pi / 2, child: Row( children: [ Expanded( child: Text( "Cancel Trip", style: Theme.of(context) .textTheme .body1 .apply(color: Colors.white), ), ), Icon(Icons.clear, color: Colors.white60), ], ), ), ),

The transform widget allows you to rotate the child and have that fancy look, add in that top left border-radius and you get that amazing look!

THE END.

I hope you enjoyed reading this article. As always feel free to use the code in your own personal project. Play around with the code as it’s by doing that that you will improve your skill.

Don’t forget to follow me on Twitter: @cybdom and share this tutorial!