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.cupertino_colors.SYSTEM_BACKGROUND),
)
page.navigation_bar = ft.NavigationBar(
destinations=[
ft.NavigationDestination(icon=ft.icons.EXPLORE, label="Explore"),
ft.NavigationDestination(icon=ft.icons.COMMUTE, label="Commute"),
ft.NavigationDestination(
icon=ft.icons.BOOKMARK_BORDER,
selected_icon=ft.icons.BOOKMARK,
label="Bookmark",
),
],
border=ft.Border(
top=ft.BorderSide(color=ft.cupertino_colors.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.app(target=main)
By setting just page.adaptive = True
you can make you app looking awesome on both iOS and Android devices:
iPhone
Android
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 by default is False
. When using a Material control with adaptive
property set to True
, a different control will be created depending on the platform, for example:
ft.Checkbox(adaptive=True, value=True, label="Adaptive Checkbox")
Flet checks the value of page.platform
property and if it is ft.PagePlatform.IOS
or ft.PagePlatform.MACOS
, Cupertino control will be created; in all other cases Material control will be created.
adaptive
property can be set for an individual control or a container control such as Row
, Column
or any other control that has content
or controls
property. If container control is adaptive, all its child controls will be adaptive, unless adaptive
property is explicitely set to False
for a child control.
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 AdaptiveNavigationDestination
control that will be displaying different icon on iOS and Android:
class AdaptiveNavigationDestination(ft.NavigationDestination):
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
)
We will use AdaptiveNavigationDestination
in NavigationBar
:
import flet as ft
from adaptive_navigation_destination import AdaptiveNavigationDestination
def main(page):
page.adaptive = True
page.navigation_bar = ft.NavigationBar(
selected_index=2,
destinations=[
AdaptiveNavigationDestination(
ios_icon=ft.cupertino_icons.PERSON_3_FILL,
android_icon=ft.icons.PERSON,
label="Contacts",
),
AdaptiveNavigationDestination(
ios_icon=ft.cupertino_icons.CHAT_BUBBLE_2,
android_icon=ft.icons.CHAT,
label="Chats",
),
AdaptiveNavigationDestination(
ios_icon=ft.cupertino_icons.SETTINGS,
android_icon=ft.icons.SETTINGS,
label="Settings",
),
],
)
page.update()
ft.app(target=main)
Now the NavigationBar and icons within it will look like different on Android and iOS:
iOS
Android
You may utilise reusable controls approach to adapt your app not only depending on the platform
but also use page.web
property to have different UI depending on wether the app is running in a browser or not, or even combine platform
and web
properties to have specific UI for your MACOS or Windows desktop apps.