Create Real Estate App UI Design in Flutter | devhubspot

Flutter UI Flutter app UI design real estate real estate app flutter

Hi, in this video I will teach you how to design a real estate app in Flutter and then walk you through the steps step by step. 

Create a Flutter App

If everything is properly set up, then to create a project we can simply run the following command in our desired local directory:

flutter create newsapp

After we've set up the project, we can navigate inside the project directory and execute the following command in the terminal to run the project in either an available emulator or an actual device:

flutter run

First, we need to make some simple configurations to the default boilerplate code in the main.dart file. We'll remove some default code and add the following code

import 'package:estateapp/screens/welcome.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Estate App',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: WelcomeScreen(),
    );
  }
}

Before Starting the code create a constants folder and create colors.dart file inner constants folder and add the following code : 

import 'package:flutter/material.dart';

const Color white = Colors.white;
const Color black = Colors.black;
const Color red = Colors.red;
const Color darkBlue = Color.fromRGBO(19, 26, 44, 1.0);
const Color lightBlue = Color.fromRGBO(19, 26, 44, 0.7);

After creating a model folder and create house.dart file inner model folder and add the following code : 

class House {
  String imageUrl = "";
  String address;
  String description;
  double price;
  int bedRooms;
  int bathRooms;
  double sqFeet;
  int garages;
  int time;
  List<String> moreImagesUrl;
  bool isFav;

  House(
      {required this.imageUrl,
      required this.address,
      required this.description,
      required this.price,
      required this.bedRooms,
      required this.bathRooms,
      required this.sqFeet,
      required this.garages,
      required this.time,
      required this.moreImagesUrl,
      required this.isFav});
}

After creating a data folder and create data.dart file inner data folder and add the following code : 

import 'package:estateapp/model/house.dart';

final _house1 = House(
    imageUrl: 'assets/images/house1.jpeg',
    address: 'Janison, MI 49428,SF',
    description:
        'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
    price: 200.00,
    bedRooms: 4,
    bathRooms: 2,
    garages: 2,
    sqFeet: 1.416,
    time: 20,
    isFav: false,
    moreImagesUrl: [
      'assets/images/house1.jpeg',
      'assets/images/indoor1.jpg',
      'assets/images/indoor2.jpg',
      'assets/images/indoor3.jpg',
      'assets/images/indoor4.jpg',
      'assets/images/indoor5.jpg',
    ]);

final _house2 = House(
    imageUrl: 'assets/images/house2.jpeg',
    address: '351, Rockwood Dr,SF',
    description:
        'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
    price: 140.00,
    bedRooms: 4,
    bathRooms: 2,
    garages: 1,
    sqFeet: 1.416,
    time: 30,
    isFav: false,
    moreImagesUrl: [
      'assets/images/house2.jpeg',
      'assets/images/indoor1.jpg',
      'assets/images/indoor2.jpg',
      'assets/images/indoor3.jpg',
      'assets/images/indoor4.jpg',
      'assets/images/indoor5.jpg',
    ]);

final _house3 = House(
    imageUrl: 'assets/images/house2.jpeg',
    address: '354, Hendrywood Dr,SF',
    description:
        'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
    price: 210.00,
    bedRooms: 5,
    bathRooms: 3,
    garages: 1,
    sqFeet: 1.700,
    time: 30,
    isFav: false,
    moreImagesUrl: [
      'assets/images/house3.jpeg',
      'assets/images/indoor1.jpg',
      'assets/images/indoor2.jpg',
      'assets/images/indoor3.jpg',
      'assets/images/indoor4.jpg',
      'assets/images/indoor5.jpg',
    ]);

final _house4 = House(
    imageUrl: 'assets/images/house4.png',
    address: 'Manison, MI 49526,SF',
    description:
        'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
    price: 170.00,
    bedRooms: 2,
    bathRooms: 1,
    garages: 1,
    sqFeet: 1.210,
    time: 30,
    isFav: false,
    moreImagesUrl: [
      'assets/images/house4.png',
      'assets/images/indoor1.jpg',
      'assets/images/indoor2.jpg',
      'assets/images/indoor3.jpg',
      'assets/images/indoor4.jpg',
      'assets/images/indoor5.jpg',
    ]);

final _house5 = House(
    imageUrl: 'assets/images/house5.jpeg',
    address: 'BackStreet, MI 49526,SF',
    description:
        'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
    price: 150.00,
    bedRooms: 3,
    bathRooms: 1,
    garages: 1,
    sqFeet: 1.42,
    time: 240,
    isFav: false,
    moreImagesUrl: [
      'assets/images/house5.jpeg',
      'assets/images/indoor1.jpg',
      'assets/images/indoor2.jpg',
      'assets/images/indoor3.jpg',
      'assets/images/indoor4.jpg',
      'assets/images/indoor5.jpg',
    ]);

final List<House> houseList = [
  _house2,
  _house1,
  _house3,
  _house4,
  _house5,
];

List<String> categoryList = [
  '< \$220.00',
  'For Sale',
  '3-4 bed room',
  'Garages',
  'Modular kitchen'
];

After Create Welcome.dart stateful widget  file in the screens folder like screens/welcome.dart, then inside of it with the following code:

import 'package:estateapp/constants/colors.dart';
import 'package:estateapp/screens/home/home.dart';
import 'package:flutter/material.dart';

class WelcomeScreen extends StatefulWidget {
  const WelcomeScreen({super.key});

  @override
  State<WelcomeScreen> createState() => _WelcomeScreenState();
}

class _WelcomeScreenState extends State<WelcomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: lightBlue,
      body: Padding(
        padding: const EdgeInsets.all(30.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Spacer(),
            CircleAvatar(
              radius: 50,
              backgroundColor: white,
              child: Image.asset('assets/images/villa.png'),
            ),
            const SizedBox(height: 30),
            const Center(
              child: Text("Welcome to Estate App",
                  style: TextStyle(
                      color: white, fontSize: 20, fontWeight: FontWeight.bold)),
            ),
            const SizedBox(height: 10),
            const Center(
              child: Text("Find your home with us",
                  style: TextStyle(color: white, fontSize: 15)),
            ),
            const Spacer(),
            Padding(
              padding: const EdgeInsets.only(bottom: 20),
              child: GestureDetector(
                onTap: () {
                  Navigator.push(context,
                      MaterialPageRoute(builder: (context) => HomeScreen()));
                },
                child: ElevatedButton(
                  onPressed: () {
                    Navigator.push(context,
                        MaterialPageRoute(builder: (context) => HomeScreen()));
                  },
                  child: const Text("Get Stated",
                      style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.bold,
                          color: darkBlue)),
                  style: ElevatedButton.styleFrom(
                      backgroundColor: white,
                      padding: const EdgeInsets.symmetric(
                          horizontal: 100, vertical: 15),
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(30))),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

After Create home.dart stateful widget  file in the screens folder like screens/home/home.dart, then inside of it with the following code:

import 'package:estateapp/screens/home/components/app_bar.dart';
import 'package:estateapp/screens/home/components/categories.dart';
import 'package:estateapp/screens/home/components/housecard.dart';
import 'package:estateapp/screens/home/components/search.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          const AppbarHome(),
          const SearchField(),
          SizedBox(
            height: MediaQuery.of(context).size.height * 0.01,
          ),
          Categories(),
          HouseCard()
        ],
      ),
    );
  }
}

Before adding code home.dart create files on the components folder path screens/home/components/

app_bar.dart

import 'package:estateapp/constants/colors.dart';
import 'package:flutter/material.dart';

class AppbarHome extends StatelessWidget {
  final TextStyle textStyle = const TextStyle(
      fontSize: 16.0, fontWeight: FontWeight.bold, color: darkBlue);

  const AppbarHome({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.only(bottom: 10, top: 60),
      padding: const EdgeInsets.symmetric(horizontal: 30 / 1.5),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text("Hello!"),
              Text(
                "Devhubspot",
                style: textStyle,
              )
            ],
          ),
          Container(
            height: 50.0,
            width: 50.0,
            decoration: BoxDecoration(
                color: white, borderRadius: BorderRadius.circular(25.0)),
            child: const Icon(
              Icons.person,
              color: darkBlue,
              size: 25.0,
            ),
          )
        ],
      ),
    );
  }
}

categories.dart

import 'package:estateapp/constants/colors.dart';
import 'package:estateapp/data/data.dart';
import 'package:flutter/material.dart';

class Categories extends StatefulWidget {
  const Categories({super.key});

  @override
  State<Categories> createState() => _CategoriesState();
}

class _CategoriesState extends State<Categories> {
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Padding(
      padding: const EdgeInsets.only(left: 30.0, top: 15.0, bottom: 30),
      child: Container(
        height: size.height * 0.05,
        child: ListView.builder(
          physics: const BouncingScrollPhysics(),
          scrollDirection: Axis.horizontal,
          itemCount: categoryList.length,
          itemBuilder: (context, index) {
            return buildCategory(context, index);
          },
        ),
      ),
    );
  }

  Widget buildCategory(BuildContext context, int index) {
    return GestureDetector(
      onTap: () {
        setState(() {
          selectedIndex = index;
        });
      },
      child: Padding(
        padding: const EdgeInsets.only(right: 10),
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 15.0),
          decoration: BoxDecoration(
              color: selectedIndex == index ? darkBlue : black.withOpacity(0.1),
              borderRadius: BorderRadius.circular(20)),
          child: Center(
            child: Text(
              categoryList[index],
              style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: selectedIndex == index ? white : black),
            ),
          ),
        ),
      ),
    );
  }
}

housecard.dart

import 'package:estateapp/constants/colors.dart';
import 'package:estateapp/data/data.dart';
import 'package:estateapp/model/house.dart';
import 'package:estateapp/screens/detail/detail.dart';
import 'package:flutter/material.dart';

class HouseCard extends StatefulWidget {
  const HouseCard({super.key});

  @override
  State<HouseCard> createState() => _HouseCardState();
}

class _HouseCardState extends State<HouseCard> {
  @override
  Widget build(BuildContext context) {
    return Expanded(
        child: ListView.builder(
      physics: const BouncingScrollPhysics(),
      itemCount: houseList.length,
      itemBuilder: (context, index) {
        return buildHouse(context, index);
      },
    ));
  }

  Widget buildHouse(BuildContext context, int index) {
    Size size = MediaQuery.of(context).size;
    House house = houseList[index];

    return GestureDetector(
      onTap: () {
        Navigator.push(context,
            MaterialPageRoute(builder: (_) => DetailScreen(house: house)));
      },
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 15.0),
        child: Container(
          height: 250,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Stack(
                children: [
                  ClipRRect(
                    borderRadius: BorderRadius.circular(20),
                    child: Image(
                        image: AssetImage(house.imageUrl),
                        fit: BoxFit.cover,
                        width: size.width,
                        height: 180),
                  ),
                  Positioned(
                    right: 15.0,
                    top: 15.0,
                    child: Container(
                      decoration: BoxDecoration(
                        color: white,
                        borderRadius: BorderRadius.circular(15),
                      ),
                      child: IconButton(
                        icon: house.isFav
                            ? Icon(Icons.favorite_rounded, color: red)
                            : Icon(Icons.favorite_border_rounded, color: black),
                        onPressed: () {
                          setState(() {
                            house.isFav = !house.isFav;
                          });
                        },
                      ),
                    ),
                  )
                ],
              ),
              Row(
                children: [
                  Text(
                    '\$${house.price.toStringAsFixed(3)}',
                    style: const TextStyle(
                        fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(width: 10),
                  Expanded(
                    child: Text(
                      house.address,
                      overflow: TextOverflow.ellipsis,
                      style: TextStyle(
                          fontSize: 15, color: black.withOpacity(0.4)),
                    ),
                  )
                ],
              ),
              Row(
                children: [
                  Text(
                    '${house.bedRooms} bedrooms / ',
                    style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
                  ),
                  Text(
                    '${house.bathRooms} bathrooms / ',
                    style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
                  ),
                  Text(
                    '${house.sqFeet} sqft',
                    style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

search.dart

import 'package:estateapp/constants/colors.dart';
import 'package:flutter/material.dart';

class SearchField extends StatelessWidget {
  const SearchField({super.key});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 30 / 1.5),
      child: Material(
        elevation: 2.0,
        borderRadius: const BorderRadius.all(Radius.circular(30.0)),
        child: TextFormField(
          style: const TextStyle(color: black, fontSize: 16.0),
          cursorColor: Colors.grey.shade300,
          decoration: const InputDecoration(
              contentPadding:
                  EdgeInsets.symmetric(horizontal: 32.0, vertical: 14.0),
              suffixIcon: Material(
                elevation: 0,
                borderRadius: BorderRadius.all(Radius.circular(30.0)),
                child: Icon(
                  Icons.search,
                  color: Colors.black45,
                ),
              ),
              border: InputBorder.none,
              hintText: "Search for House..."),
        ),
      ),
    );
  }
}

After Create detail.dart stateful widget  file in the screens folder like screens/detail.dart, then inside of it with the following code:

import 'package:estateapp/model/house.dart';
import 'package:estateapp/screens/detail/components/appbar.dart';
import 'package:estateapp/screens/detail/components/carousel_images.dart';
import 'package:estateapp/screens/detail/components/house_detail.dart';
import 'package:flutter/material.dart';

class DetailScreen extends StatefulWidget {
  final House house;

  const DetailScreen({super.key, required this.house});

  @override
  State<DetailScreen> createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Stack(
              children: [
                CarouselImages(widget.house.moreImagesUrl),
                AppBarDetail()
              ],
            ),
            HouseDetail(widget.house)
          ],
        ),
      ),
    );
  }
}

Before adding code details.dart create files on the components folder path screens/details/components/

appbar.dart

import 'package:estateapp/constants/colors.dart';
import 'package:flutter/material.dart';

class AppBarDetail extends StatelessWidget {
  const AppBarDetail({super.key});

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;

    return Padding(
      padding: const EdgeInsets.only(left: 30, right: 30, top: 30),
      child: Container(
        height: size.height * 0.1,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            InkWell(
              onTap: () {
                Navigator.pop(context);
              },
              child: Container(
                height: 50,
                width: 50,
                decoration: BoxDecoration(
                    color: darkBlue,
                    border: Border.all(color: darkBlue),
                    borderRadius: BorderRadius.circular(15)),
                child: const Icon(Icons.chevron_left_rounded, color: white),
              ),
            ),
            Container(
              height: 50,
              width: 50,
              decoration: BoxDecoration(
                  color: darkBlue, borderRadius: BorderRadius.circular(15)),
              child: Icon(
                Icons.favorite_border_rounded,
                color: white,
              ),
            )
          ],
        ),
      ),
    );
  }
}

carousel_images.dart

import 'package:flutter/material.dart';
import 'package:flutter_image_slideshow/flutter_image_slideshow.dart';

class CarouselImages extends StatefulWidget {
  final List<String> imagesListUrl;

  CarouselImages(this.imagesListUrl);

  @override
  State<CarouselImages> createState() => _CarouselImagesState();
}

class _CarouselImagesState extends State<CarouselImages> {
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;

    debugPrint(widget.imagesListUrl.length.toString());

    List<AssetImage> imageWidgets =
        widget.imagesListUrl.take(6).map((imageurl) {
      return AssetImage(imageurl);
    }).toList();

    return Container(
      height: size.height * 0.35,
      child: ImageSlideshow(
          indicatorColor: Colors.black,
          onPageChanged: (value) {
            debugPrint('Page changed: $value');
          },
          // autoPlayInterval: 3000,
          isLoop: true,
          children: [
            Container(
              height: 200,
              child: ListView.builder(
                physics: BouncingScrollPhysics(),
                scrollDirection: Axis.horizontal,
                itemCount: widget.imagesListUrl.length,
                itemBuilder: (context, index) {
                  return Image.asset(
                    widget.imagesListUrl[index],
                    fit: BoxFit.cover,
                  );
                },
              ),
            )
          ]

          // [
          //   Image.asset(
          //     'images/sample_image_1.jpg',
          //     fit: BoxFit.cover,
          //   ),
          //   Image.asset(
          //     'images/sample_image_2.jpg',
          //     fit: BoxFit.cover,
          //   ),
          //   Image.asset(
          //     'images/sample_image_3.jpg',
          //     fit: BoxFit.cover,
          //   ),
          // ],
          ),
    );

    // Image.asset(widget.imagesListUrl.first));
  }
}

house_detail.dart

import 'package:estateapp/constants/colors.dart';
import 'package:estateapp/model/house.dart';
import 'package:flutter/material.dart';

class HouseDetail extends StatefulWidget {
  final House house;

  HouseDetail(this.house);

  @override
  State<HouseDetail> createState() => _HouseDetailState();
}

class _HouseDetailState extends State<HouseDetail> {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: ListView(
        physics: BouncingScrollPhysics(),
        shrinkWrap: true,
        children: [
          Padding(
            padding: EdgeInsets.only(bottom: 30, left: 30, right: 30),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      '\$${widget.house.price.toStringAsFixed(3)}',
                      style:
                          TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
                    ),
                    SizedBox(
                      height: 5,
                    ),
                    Text(
                      widget.house.address,
                      style: TextStyle(
                          fontSize: 15,
                          color: black.withOpacity(0.4),
                          fontWeight: FontWeight.w600),
                    )
                  ],
                ),
                Text(
                  '${widget.house.time} hours ago',
                  style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
                )
              ],
            ),
          ),
          Padding(
            padding: EdgeInsets.only(left: 30.0, bottom: 30.0),
            child: Text(
              "House Infomation",
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
          ),
          Padding(
            padding: EdgeInsets.only(left: 30, right: 30, bottom: 120),
            child: Text(
              widget.house.description,
              style: TextStyle(color: black.withOpacity(0.4), height: 2.0),
              textAlign: TextAlign.justify,
            ),
          )
        ],
      ),
    );
  }
}
Output:


Flutter UI Flutter app UI design real estate real estate app flutter
Comments

AdBlock Detected!

Our website is made possible by displaying ads to our visitors. Please supporting us by whitelisting our website.