Flight Booking
Loading preview
Starting the Flutter app
A showcase of Flutter's flight booking functionality
import 'package:flutter/material.dart';
class FlightBooking extends StatefulWidget {
const FlightBooking({super.key});
@override
State<FlightBooking> createState() => _FlightBookingState();
}
class _FlightBookingState extends State<FlightBooking> {
var _tripType = 'Round trip';
var _passengers = 1;
var _cabin = 'Economy';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flight Booking')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
SegmentedButton<String>(
segments: const [
ButtonSegment(value: 'Round trip', label: Text('Round trip')),
ButtonSegment(value: 'One way', label: Text('One way')),
ButtonSegment(value: 'Multi-city', label: Text('Multi-city')),
],
selected: {_tripType},
onSelectionChanged: (s) => setState(() => _tripType = s.first),
),
const SizedBox(height: 20),
TextField(
decoration: InputDecoration(
labelText: 'From',
hintText: 'Origin city',
prefixIcon: const Icon(Icons.flight_takeoff),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
const SizedBox(height: 12),
TextField(
decoration: InputDecoration(
labelText: 'To',
hintText: 'Destination city',
prefixIcon: const Icon(Icons.flight_land),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: 'Depart',
prefixIcon: const Icon(Icons.calendar_today),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
),
if (_tripType == 'Round trip') ...[
const SizedBox(width: 12),
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: 'Return',
prefixIcon: const Icon(Icons.calendar_today),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
),
],
],
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: DropdownButtonFormField<int>(
initialValue: _passengers,
decoration: InputDecoration(
labelText: 'Passengers',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
),
items: [1, 2, 3, 4, 5]
.map((n) => DropdownMenuItem(value: n, child: Text('$n')))
.toList(),
onChanged: (v) => setState(() => _passengers = v ?? 1),
),
),
const SizedBox(width: 12),
Expanded(
child: DropdownButtonFormField<String>(
initialValue: _cabin,
decoration: InputDecoration(
labelText: 'Class',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
),
items: ['Economy', 'Premium', 'Business', 'First']
.map((c) => DropdownMenuItem(value: c, child: Text(c)))
.toList(),
onChanged: (v) => setState(() => _cabin = v ?? _cabin),
),
),
],
),
const SizedBox(height: 24),
FilledButton(
onPressed: () => _showDemo(context, 'Search Flights (demo)'),
style: FilledButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Text('Search Flights'),
),
],
),
);
}
}
void _showDemo(BuildContext context, String message) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(message)));
}
Add it to your project
Copies the Dart source into your app, so you own it. Flutter SDK only, no extra packages.
First time? Run dart pub global activate fluttertemplates_dev, or read the CLI guide.
How it works
_tripType, _passengers and _cabin are the tracked values. Return shows only for Round trip, with Depart filling the row otherwise, but Multi-city adds no legs yet. Cities and dates are plain TextFields without controllers, so there’s no date picker, and Search Flights shows a demo SnackBar. _passengers and _cabin hold the dropdown choices, ready for a search request.
Adapting it
- Add leg rows for
Multi-city. - Make the
DepartandReturnfieldsreadOnly, and callshowDateRangePickeron tap. - Add
Formvalidation, collecting values into your flight search request.