Adaptive apps
Flet framework allows you to develop adaptive apps which means having a single codebase that will deliver different look depending on the device's platform.
Below is the example of a very simple app that has a different look on iOS and Android platforms:
import flet as ft
def main(page):
page.adaptive = True
page.appbar = ft.AppBar(
leading=ft.TextButton("New", style=ft.ButtonStyle(padding=0)),
title=ft.Text("Adaptive AppBar"),
actions=[
ft.IconButton(ft.cupertino_icons.ADD, style=ft.ButtonStyle(padding=0))
],
bgcolor=ft.Colors.with_opacity(0.04, ft.CupertinoColors.SYSTEM_BACKGROUND),
)
page.navigation_bar = ft.NavigationBar(
destinations=[
ft.NavigationBarDestination(icon=ft.Icons.EXPLORE, label="Explore"),
ft.NavigationBarDestination(icon=ft.Icons.COMMUTE, label="Commute"),
ft.NavigationBarDestination(
icon=ft.Icons.BOOKMARK_BORDER,
selected_icon=ft.Icons.BOOKMARK,
label="Bookmark",
),
],
border=ft.Border(
top=ft.BorderSide(color=ft.CupertinoColors.SYSTEM_GREY2, width=0)
),
)
page.add(
ft.SafeArea(
ft.Column(
[
ft.Checkbox(value=False, label="Dark Mode"),
ft.Text("First field:"),
ft.TextField(keyboard_type=ft.KeyboardType.TEXT),
ft.Text("Second field:"),
ft.TextField(keyboard_type=ft.KeyboardType.TEXT),
ft.Switch(label="A switch"),
ft.FilledButton(content=ft.Text("Adaptive button")),
ft.Text("Text line 1"),
ft.Text("Text line 2"),
ft.Text("Text line 3"),
]
)
)
)
ft.run(main)
By setting just page.adaptive = True
you can make you app looking awesome on both iOS and Android devices:
Material and Cupertino controls#
Most of Flet controls are based on Material design.
There is also a number of iOS-style controls in Flet that are called Cupertino controls.
Cupertino controls usually have a matching Material control that has adaptive
property
which defaults toFalse
. When using a Material control with adaptive
property set to True
,
a different control will
be created depending on the platform, for example:
Flet checks the value of Page.platform
property and if it is
PagePlatform.IOS
or ft.PagePlatform.MACOS
, Cupertino control will be created;
in all other cases Material control will be created.
Note
adaptive
property can be set for an individual control or
a container-controls (ex: Row
, Column
) that has children controls.
If a container-control is made adaptive, all its children will be adaptive too,
unless adaptive
property is explicitly set to False
for a child control.
Material vs Cupertino
Below is the list of adaptive Material controls and their matching Cupertino controls:
Custom adaptive controls#
While Flet offers a number of controls that will be adapted to a platform
automatically using their adaptive
property, there will be
cases when you need more specific adaptive UI presentation, for example, using different
icon, background color, padding, etc., depending on the platform.
With Flet, you can create your own reusable custom controls in Python that will inherit from a Flet control and implement specific properties you need.
In the example below, we are creating a new AdaptiveNavigationBarDestination
custom control that will be displaying different icon on iOS and Android, and use it
as destination for the NavigationBar
:
import flet as ft
class AdaptiveNavigationBarDestination(ft.NavigationBarDestination):
def __init__(self, ios_icon, android_icon, label):
super().__init__()
self._ios_icon = ios_icon
self._android_icon = android_icon
self.label = label
def build(self):
# we can check for platform in build method because self.page is known
self.icon = (
self._ios_icon
if self.page.platform == ft.PagePlatform.IOS
or self.page.platform == ft.PagePlatform.MACOS
else self._android_icon
)
def main(page: ft.Page):
page.adaptive = True
page.navigation_bar = ft.NavigationBar(
selected_index=2,
destinations=[
AdaptiveNavigationBarDestination(
ios_icon=ft.cupertino_icons.PERSON_3_FILL,
android_icon=ft.Icons.PERSON,
label="Contacts",
),
AdaptiveNavigationBarDestination(
ios_icon=ft.cupertino_icons.CHAT_BUBBLE_2,
android_icon=ft.Icons.CHAT,
label="Chats",
),
AdaptiveNavigationBarDestination(
ios_icon=ft.cupertino_icons.SETTINGS,
android_icon=ft.Icons.SETTINGS,
label="Settings",
),
],
)
page.update()
ft.run(main)
Now the NavigationBar
and icons within it will look like different on Android and iOS:
Note
You may utilise reusable controls approach to
adapt your app not only depending on the Page.platform
,
but also use Page.web
property to have different UI depending on whether the
app is running in a browser or not, or even combine the usage of both properties to have specific
UI for your apps.