Home Page - Food Delivery App in Maui
Please, support my blog by clicking on our sponsors ad!
Follow basic setup from here
You will get all page of this app from FoodDeliveryApp Menu on top.
Let's Create Model
MenuModel
public class MenuModel
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
public ImageSource Image { get; set; }
}
RestaurantModel
public class RestaurantModel
{
public string Name { get; set; }
public string Description { get; set; }
public string Rating { get; set; }
public ImageSource Image { get; set; }
public List<MenuModel> Menus { get; set; } = new List<MenuModel>();
}
BannerModel
public class BannerModel
{
public ImageSource Image { get; set; }
}
BaseViewModel
public class BaseViewModel : INotifyPropertyChanged
{
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
MainViewModel
public class MainViewModel
{
public List<BannerModel> BannerModel { get; set; } = new List<BannerModel>();
public List<RestaurantModel> Restaurants { get; set; } = new List<RestaurantModel>();
public List<RestaurantModel> FirstSlotRestaurants { get; set; } = new List<RestaurantModel>();
public List<RestaurantModel> SecondSlotRestaurants { get; set; } = new List<RestaurantModel>();
public List<MenuModel> Menus { get; set; } = new List<MenuModel>();
}
HomeViewModel
public class HomeViewModel : BaseViewModel
{
public Command LoadBannerCommand { get; set; }
private List<MainViewModel> bannerVM;
public HomeViewModel()
{
LoadBannerCommand = new Command(async () => await ExecuteLoadBannerCommand());
}
public List<MainViewModel> vm
{
get
{
return bannerVM;
}
set
{
SetProperty(ref bannerVM, value);
}
}
public async Task ExecuteLoadBannerCommand()
{
try
{
IsBusy = true;
vm = new List<MainViewModel>();
vm.Add(new MainViewModel { BannerModel = new List<BannerModel>() });
List<BannerModel> list = new List<BannerModel>();
list.Add(new BannerModel { Image = "https://cdn.grabon.in/gograbon/images/web-images/uploads/1658919135375/swiggy-coupons.jpg" });
list.Add(new BannerModel { Image = "https://www.dealsshutter.com/uploads/social_images/stores/swiggy-coupons-social-image-final-1621831150.jpg" });
list.Add(new BannerModel { Image = "https://www.couponmoto.com/boards/wp-content/uploads/2019/02/Swiggy-Banner.png" });
list.Add(new BannerModel { Image = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8CF6zXRURcFjGNS4twbPJefG596hzaydN1d_oC4Xtx391t_BOIxqLXsfUgv4RlK0V2JY" });
list.Add(new BannerModel { Image = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR9-SipuwkwtNCQCBbr47cU0-tWqYfO4QJLJQ" });
List<MenuModel> menus = new List<MenuModel>();
menus.Add(new MenuModel { Name = "Locho", Description = "Locho", Price = 25, Image = "https://cdn-bkdna.nitrocdn.com/byIcNObNLXVFaYWLstICKAkCMytzVoyD/assets/static/optimized/rev-02ea418/wp-content/uploads/2021/03/LOCHO.jpg" });
menus.Add(new MenuModel { Name = "Pani Puri", Description = "Locho", Price = 25, Image = "https://akm-img-a-in.tosshub.com/indiatoday/images/story/201708/dish-story_647_081417052301.jpg" });
menus.Add(new MenuModel { Name = "Chole Bhature", Description = "Chole Bhature", Price = 25, Image = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXh5LCoOMSM_9pmgcOROJRd4If-6ciXX_bkw" });
menus.Add(new MenuModel { Name = "Lithi Chokha", Description = "Locho", Price = 25, Image = "https://img.traveltriangle.com/blog/wp-content/uploads/2018/01/shutterstock_4148348021.jpg" });
menus.Add(new MenuModel { Name = "Indian Food", Description = "Indian Food", Price = 25, Image = "https://t3.ftcdn.net/jpg/01/43/83/08/360_F_143830808_V7n31HxcS8duJIVr3opWzG4FCkDQZK4v.jpg" });
List<RestaurantModel> restaurants = new List<RestaurantModel>();
restaurants.Add(new RestaurantModel
{
Name = "Table 101",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://hips.hearstapps.com/hmg-prod/images/img-6171-jpg-1516034404.jpg",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Foina",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://im1.dineout.co.in/images/uploads/restaurant/sharpen/4/l/h/p4185-164156150261d83d9ec6ca8.jpg",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Kabab and Kurries",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTx0hX-qswrn0vA1ZGogh05cd6dbRiJqbG-ww",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Rasoi Kitchen",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTO5nlpGTbABZretJas2xH6RDnWIhTbiRoIOA",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Mabruk",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://threebestrated.in/images/MahalaxmiFastFoodandJuiceCorner-Surat-GJ.jpeg",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Saptami",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://i0.wp.com/swadishta.de/wp-content/uploads/2021/01/Thali.jpg",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Yeda Republic",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://i0.wp.com/indiacurrents.com/wp-content/uploads/2022/09/pesarratu.jpg",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Peshawari",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSCAOb9b2dUqUFuUbzbYlMWu4qLwrxjRs_2Dg",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Solitare Restaurant",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://static.toiimg.com/thumb/56624568/308796_287027921321520_585680932_n.jpg",
Menus = menus
});
restaurants.Add(new RestaurantModel
{
Name = "Gallery Cafe",
Description = "Good Option",
Rating = "4.0 (10k)",
Image = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQsuxe-gEy1j2uKXJG9pUWdx-ZGalqtGCDStw",
Menus = menus
});
vm[0].BannerModel = list;
bannerVM[0].Restaurants = restaurants;
bannerVM[0].FirstSlotRestaurants = restaurants.Take(3).ToList();
bannerVM[0].SecondSlotRestaurants = restaurants.Reverse<RestaurantModel>().Take(7).ToList();
bannerVM[0].Menus = menus;
}
catch (Exception ex)
{
await App.Current.MainPage.DisplayAlert("", ex.Message, "OK");
}
IsBusy = false;
}
public void OnAppearing()
{
IsBusy = true;
}
}
Let's Create a Control
ProductHomeControl.xaml
ProductHomeControl.xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FoodDeliveryApp.Controls.ProductHomeControl"
xmlns:fontAwesome="clr-namespace:FoodDeliveryApp.Utilities">
<Grid ColumnDefinitions="Auto,Auto,*,Auto" RowDefinitions="Auto,Auto" ColumnSpacing="5" RowSpacing="5">
<Label Grid.Column="0" Grid.Row="0" Text="{x:Static fontAwesome:FontAwesomeSolid.Shopping_Bag}"
FontSize="15" TextColor="{x:StaticResource Primary}" FontFamily="FontAwesome" ></Label>
<Label Grid.Column="1" Grid.Row="0" Text="Work" TextColor="{x:StaticResource Secondary}"
FontAttributes="Bold" ></Label>
<Label Grid.Column="2" Grid.Row="0" Text="{x:Static fontAwesome:FontAwesomeSolid.Angle_Down}"
VerticalOptions="End" FontSize="20" TextColor="{x:StaticResource Gray}" FontFamily="FontAwesome" >
</Label>
<Label Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" Text="{x:Static fontAwesome:FontAwesomeSolid.User_Circle}"
FontSize="30" TextColor="{x:StaticResource Gray}" FontFamily="FontAwesome" ></Label>
<Label Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1" Text="1600 Amphitheatre Parkway
Mountain View, CA 94043, USA." TextColor="{x:StaticResource Gray}"></Label>
</Grid>
</ContentView>
RoundCornerImage.Xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FoodDeliveryApp.Controls.RoundCornerImage">
<Grid RowDefinitions="Auto,Auto" Padding="5">
<Frame Grid.Row="0" Padding="0" CornerRadius="20">
<Image x:Name="img" HeightRequest="80" Aspect="AspectFill"></Image>
</Frame>
<Label Grid.Row="1" x:Name="lbl" TextColor="{x:StaticResource Gray}" HorizontalOptions="Center" Margin="0,8,0,0"></Label>
</Grid>
</ContentView>
RoundCornerImage.Xaml.cs
public partial class RoundCornerImage : ContentView
{
public RoundCornerImage()
{
InitializeComponent();
}
public ImageSource Image { get => img.Source; set => img.Source = value; }
public bool IsAnimation { get => img.IsAnimationPlaying; set => img.IsAnimationPlaying = value; }
public string Title { get => lbl.Text; set => lbl.Text = value; }
}
Let's Create Template
BannerTemplate.Xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FoodDeliveryApp.Pages.Products.Template.BannerTemplate"
xmlns:model="clr-namespace:FoodDeliveryApp.Models">
<StackLayout Padding="5">
<Frame x:DataType="model:BannerModel" Padding="0" CornerRadius="10">
<Image Source="{Binding Image}" HeightRequest="150" Aspect="AspectFill"></Image>
</Frame>
</StackLayout>
</ContentView>
ProductTemplate.xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FoodDeliveryApp.Pages.Products.Template.ProductTemplate">
<Grid Padding="5" ColumnSpacing="10" RowDefinitions="Auto" RowSpacing="0" ColumnDefinitions="150,*">
<Frame Padding="0" CornerRadius="10" Grid.Row="0" Grid.Column="0" Grid.RowSpan="4">
<Image Source="{Binding Image}" HeightRequest="150" Aspect="AspectFill"></Image>
</Frame>
<StackLayout Grid.Row="0" Grid.Column="1" VerticalOptions="CenterAndExpand">
<Label Text="{Binding Name}" TextColor="{x:StaticResource Gray}" VerticalOptions="Start" FontAttributes="Bold"></Label>
<Label Text="{Binding Rating}" TextColor="{x:StaticResource Gray}" FontAttributes="Bold"></Label>
<Label Text="{Binding Description}" TextColor="{x:StaticResource Gray}" ></Label>
<Label Text="Gopipura . 15km" TextColor="{x:StaticResource Gray}" ></Label>
</StackLayout>
</Grid>
</ContentView>
Let's Create Home Page
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FoodDeliveryApp.Pages.Products.Home"
xmlns:control="clr-namespace:FoodDeliveryApp.Controls"
xmlns:fontAwesome="clr-namespace:FoodDeliveryApp.Utilities"
xmlns:vm="clr-namespace:FoodDeliveryApp.ViewModels"
xmlns:model="clr-namespace:FoodDeliveryApp.Models"
xmlns:template="clr-namespace:FoodDeliveryApp.Pages.Products.Template"
Title="Home"
Shell.NavBarIsVisible="False">
<RefreshView x:Name="refreshView" x:DataType="vm:HomeViewModel" Command="{Binding LoadBannerCommand}"
IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<Grid RowDefinitions="Auto,Auto,*" Padding="10" RowSpacing="10" x:DataType="vm:HomeViewModel" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<control:ProductHomeControl Grid.Row="0"></control:ProductHomeControl>
<Frame Padding="12" Grid.Row="1" BackgroundColor="#f8f8f8" BorderColor="#f8f8f8" HasShadow="True">
<Grid ColumnDefinitions="*,Auto,Auto,Auto" ColumnSpacing="10">
<Label Grid.Column="0" Text="Search,Order,Enjoy,Repeat" TextColor="{x:StaticResource Gray}"></Label>
<Label Grid.Column="1" Text="{x:Static fontAwesome:FontAwesomeSolid.Search}" TextColor="{x:StaticResource Gray}" FontSize="20" FontFamily="FontAwesome"></Label>
<BoxView Grid.Column="2" BackgroundColor="{x:StaticResource Gray}" HeightRequest="20" WidthRequest="1"></BoxView>
<Label Grid.Column="3" Text="{x:Static fontAwesome:FontAwesomeSolid.Microphone}" FontSize="20" TextColor="{x:StaticResource Secondary}" FontFamily="FontAwesome">
</Label>
</Grid>
</Frame>
<ListView x:DataType="vm:HomeViewModel" x:Name="listView" ItemsSource="{Binding vm}" Grid.Row="2" HasUnevenRows="True" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid x:DataType="vm:MainViewModel" RowSpacing="10" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<Grid ColumnDefinitions="*,*,*" Grid.Row="0">
<control:RoundCornerImage Grid.Column="0" x:Name="img1" Image="https://img95.lovepik.com/photo/40104/9102.gif_wh300.gif" IsAnimation="True" Title="Tasty"></control:RoundCornerImage>
<control:RoundCornerImage Grid.Column="1" x:Name="img2" Image="https://i.pinimg.com/736x/a9/e7/b9/a9e7b9c4a3e6d2a260d68bd6fd019dc7.jpg" Title="Ofer Zone"></control:RoundCornerImage>
<control:RoundCornerImage Grid.Column="2" x:Name="img3" Image="https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExMHpwbHdiMTFiaTBoY3kyZTNueTk4bXA4eGNjcWxzOGNmaTgzaDU4ZCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/Yuy61Bd6K8STS/giphy.gif" IsAnimation="True" Title="Gourmet"></control:RoundCornerImage>
</Grid>
<StackLayout Grid.Row="1">
<!-- Other content for the list item -->
<CarouselView IndicatorView="indicatorView" Grid.Row="1" ItemsSource="{Binding BannerModel}" PeekAreaInsets="15">
<CarouselView.ItemsLayout>
<LinearItemsLayout ItemSpacing="0" Orientation="Horizontal" SnapPointsAlignment="Center" SnapPointsType="MandatorySingle"></LinearItemsLayout>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<template:BannerTemplate></template:BannerTemplate>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView x:Name="indicatorView"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center" />
</StackLayout>
<Label Text="Your trusted picks" Grid.Row="2" TextColor="{x:StaticResource Gray}" FontAttributes="Bold"></Label>
<Frame CornerRadius="20" HorizontalOptions="Start" Padding="0" Grid.Row="3" BackgroundColor="{x:StaticResource Gray}">
<Label Text="Reorder" TextColor="white" FontAttributes="Bold" Margin="10" ></Label>
</Frame>
<Grid Grid.Row="4" ColumnDefinitions="*,*,*" RowDefinitions="Auto,Auto">
<control:RoundCornerImage Grid.Row="0" Grid.Column="0" Image="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQsuxe-gEy1j2uKXJG9pUWdx-ZGalqtGCDStw" IsAnimation="True" Title="Thali"></control:RoundCornerImage>
<control:RoundCornerImage Grid.Row="0" Grid.Column="1" Image="https://static.toiimg.com/thumb/56624568/308796_287027921321520_585680932_n.jpg" Title="Ofer Zone"></control:RoundCornerImage>
<control:RoundCornerImage Grid.Row="0" Grid.Column="2" Image="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSCAOb9b2dUqUFuUbzbYlMWu4qLwrxjRs_2Dg" IsAnimation="True" Title="South Indian"></control:RoundCornerImage>
<control:RoundCornerImage Grid.Row="1" Grid.Column="0" Image="https://i0.wp.com/indiacurrents.com/wp-content/uploads/2022/09/pesarratu.jpg" IsAnimation="True" Title="Roll"></control:RoundCornerImage>
<control:RoundCornerImage Grid.Row="1" Grid.Column="1" Image="https://i0.wp.com/swadishta.de/wp-content/uploads/2021/01/Thali.jpg" Title="Full Thali"></control:RoundCornerImage>
<control:RoundCornerImage Grid.Row="1" Grid.Column="2" Image="https://threebestrated.in/images/MahalaxmiFastFoodandJuiceCorner-Surat-GJ.jpeg" IsAnimation="True" Title="Sandwich"></control:RoundCornerImage>
</Grid>
<Image Grid.Row="5" Source="https://media.tenor.com/K67T2j90c-cAAAAC/fruits-web-banner.gif" Aspect="AspectFill" IsAnimationPlaying="True"></Image>
<ListView HasUnevenRows="True" Grid.Row="6" ItemsSource="{Binding FirstSlotRestaurants}" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<template:ProductTemplate></template:ProductTemplate>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout BackgroundColor="{x:StaticResource LightGray}" Grid.Row="7" Spacing="10" Padding="10">
<Label Text="Popular Restaurant" TextColor="{x:StaticResource Gray}" FontAttributes="Bold"></Label>
<CarouselView ItemsSource="{Binding Restaurants}" >
<CarouselView.ItemsLayout>
<LinearItemsLayout ItemSpacing="0" Orientation="Horizontal" SnapPointsAlignment="Center" SnapPointsType="MandatorySingle"></LinearItemsLayout>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<template:ProductTemplate></template:ProductTemplate>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
<ListView HasUnevenRows="True" Grid.Row="8" ItemsSource="{Binding SecondSlotRestaurants}" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<template:ProductTemplate></template:ProductTemplate>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout BackgroundColor="{x:StaticResource LightGray}" Grid.Row="9" Spacing="10" Padding="10">
<Label Text="Popular Menu" TextColor="{x:StaticResource Gray}" FontAttributes="Bold"></Label>
<CarouselView ItemsSource="{Binding Menus}" >
<CarouselView.ItemsLayout>
<LinearItemsLayout ItemSpacing="0" Orientation="Horizontal" SnapPointsAlignment="Center" SnapPointsType="MandatorySingle"></LinearItemsLayout>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<template:ProductTemplate></template:ProductTemplate>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</RefreshView>
</ContentPage>
HomePage.xaml.cs
public partial class Home : ContentPage
{
HomeViewModel _viewModel;
public Home()
{
InitializeComponent();
BindingContext = _viewModel = new HomeViewModel();
}
protected override async void OnAppearing()
{
base.OnAppearing();
_viewModel.OnAppearing();
}
}
Hope this is helpfull to you. please share your feedback in comment section.
Comments
Post a Comment