Skip to main content

Flet for Android

ยท 2 min read
Feodor Fitsner
Flet founder and developer

๐Ÿค– Android support is here!

With Flet Android app you can see how your Flet Python app looks and behaves on Android devices while the app itself is running on your computer.

Similar to iOS, Flet for Android is a Flutter app written entirely in Python with the help of two open-source packages: serious_python and flet. Resulting app package is technically compliant with Google Play requirements, so you can publish awesome Android apps in pure Python.

Follow this guide to get started with testing your Flet apps on Android. Explore the app, browse gallery, play with sample projects and app settings.

FAQโ€‹

How to package my Flet app for Google Play?โ€‹

We are going to provide a project template for bootstrap Flutter app and a guide how to combine Flutter, serious_python package and your Python app together to create a standalone Android app and publish it to Google Play.

Check serious_python's readme for instructions on how create a Flutter bootstrap and package your Python app to run within it. Use flet_example project as a starting point.

Will you provide packaging for Windows, macOS and Linux?โ€‹

Yes! At the moment Flet desktop apps are packaged with flet pack command and PyInstaller. Produced app bundle adds performance and size overhead and is hard to customize, so we are going to replace it with native Flutter packaging.

Flet v0.9.0 release notesโ€‹

For testing on Android you need to upgrade your Flet installation to v0.9.0.

There were a few changes mainly to support Android in Flet CLI. Let us know if you notice something unusual.

Enjoy!

Flet for iOS

ยท 2 min read
Feodor Fitsner
Flet founder and developer

๐ŸŽ‰ Whoo-hoo, Flet app is now on App Store! ๐ŸŽ‰

With Flet iOS app you can see how your Flet Python app looks and behaves on iPhone or iPad while the app itself is running on your computer.

But it's more than just testing Flet apps on the phone! Flet mobile app itself is written in Python and its publishing to App Store is an important milestone for the entire Flet project. It is a successful proof that you can create awesome mobile apps in Python only and package them so that they are accepted in App Store!

Follow this guide to get started with testing your Flet apps on iPhone or iPad. Explore the app, browse gallery, play with sample projects and app settings.

I would like to thank Kivy project for making a toolchain for iOS which we used to compile Python interpreter and dependencies for iOS devices. We published serious_python package for adding Python runtime to any Flutter app.

FAQโ€‹

When Android is supported?โ€‹

Soon. It has #1 priority now and we've already started working on it.

How to package my Flet app for App Store?โ€‹

We are going to provide a project template for bootstrap Flutter app and a guide how to combine Flutter, serious_python package and your Python app together to create a standalone iOS app and publish it to App Store.

Later this year we'll create a CI pipeline to fully automate the process.

Check serious_python's readme for instructions on how create a Flutter bootstrap and package your Python app to run within it. Use flet_example project as a starting point.

Flet v0.8.0 release notesโ€‹

For testing on iOS you need to upgrade your Flet installation to v0.8.0.

It's been changed a lot in v0.8.0 and there were some breaking changes. Bear with us while you are upgrading to 0.8.0 and let us know if you have any troubles with it.

Enjoy!

Scrolling controls and Theming

ยท 5 min read
Feodor Fitsner
Flet founder and developer

Flet 0.7.1 enables developers changing scroll position and receiving scroll notifications from Page, View, Column, Row, ListView and GridView controls.

The release also introduces theming improvements:

Controlling scroll positionโ€‹

Scrollable controls (Page, View, Column, Row, ListView and GridView) introduce scroll_to() method to change their scroll position to either absolute offset, relative delta or jump to the control with specified key.

Moving to a key is particularly exciting as it allows simulating the navigation between page bookmarks, kind of HTML hrefs with #:

Check the source code of the example above.

See Column.scroll_to for more details about controlling scroll position.

Receiving scroll notificationsโ€‹

All scrollable controls now provide on_scroll event handler which fires when a scroll position is changed. From event object properties you can determine whether scroll operation has started, finished, changed direction or scroll position went behind scrolling extent (overscroll). You can also get updates of the current scroll position as well as dimensions of the scroll area, for example:

import flet as ft

def main(page: ft.Page):
def on_column_scroll(e: ft.OnScrollEvent):
print(
f"Type: {e.event_type}, pixels: {e.pixels}, min_scroll_extent: {e.min_scroll_extent}, max_scroll_extent: {e.max_scroll_extent}"
)

cl = ft.Column(
spacing=10,
height=200,
width=200,
scroll=ft.ScrollMode.ALWAYS,
on_scroll=on_column_scroll,
)
for i in range(0, 50):
cl.controls.append(ft.Text(f"Text line {i}", key=str(i)))

page.add(
ft.Container(cl, border=ft.border.all(1)),
)

ft.app(main)

See Column.on_scroll for more details about scroll notification.

Check infinite scroll example.

Color scheme customizationโ€‹

Until today the only way to control color scheme for your application was specifying color_scheme_seed when creating a new ft.Theme object.

This release enables you to fine tune all 30 colors based on the Material spec and used by various Flet controls.

You can even use Material Theme Builder and apply exported color palette to your app, for example:

page.theme = ft.Theme(
color_scheme=ft.ColorScheme(
primary=ft.colors.GREEN,
primary_container=ft.colors.GREEN_200
# ...
),
)

See ColorScheme class for more details.

Nested themesโ€‹

Another awesome feature of this release is nested themes!

You can have a part of your app to use a different theme or override some theme styles for specific controls.

Remember page object having theme and theme_mode properties? Now Container has theme and theme_mode properties too!

Container.theme accepts the same ft.Theme object as a page. Specifying theme_mode in the container means you don't want to inherit parent theme, but want a completely new, unique scheme for all controls inside the container. However, if the container does not have theme_mode property set then the styles from its theme property will override the ones from the parent, inherited theme:

import flet as ft

def main(page: ft.Page):
# Yellow page theme with SYSTEM (default) mode
page.theme = ft.Theme(
color_scheme_seed=ft.colors.YELLOW,
)

page.add(
# Page theme
ft.Container(
content=ft.ElevatedButton("Page theme button"),
bgcolor=ft.colors.SURFACE_VARIANT,
padding=20,
width=300,
),

# Inherited theme with primary color overridden
ft.Container(
theme=ft.Theme(color_scheme=ft.ColorScheme(primary=ft.colors.PINK)),
content=ft.ElevatedButton("Inherited theme button"),
bgcolor=ft.colors.SURFACE_VARIANT,
padding=20,
width=300,
),

# Unique always DARK theme
ft.Container(
theme=ft.Theme(color_scheme_seed=ft.colors.INDIGO),
theme_mode=ft.ThemeMode.DARK,
content=ft.ElevatedButton("Unique theme button"),
bgcolor=ft.colors.SURFACE_VARIANT,
padding=20,
width=300,
),
)

ft.app(main)

Scrollbar themeโ€‹

You can now customize the look and fill of scrollbars in your application (or a particular scroillbar with nested themes).

It could be done via page.theme.scrollbar_theme property, for example:

page.theme = ft.Theme(
scrollbar_theme=ft.ScrollbarTheme(
track_color={
ft.MaterialState.HOVERED: ft.colors.AMBER,
ft.MaterialState.DEFAULT: ft.colors.TRANSPARENT,
},
track_visibility=True,
track_border_color=ft.colors.BLUE,
thumb_visibility=True,
thumb_color={
ft.MaterialState.HOVERED: ft.colors.RED,
ft.MaterialState.DEFAULT: ft.colors.GREY_300,
},
thickness=30,
radius=15,
main_axis_margin=5,
cross_axis_margin=10,
)
)

Text themingโ€‹

Material 3 design defines 5 groups of text styles with 3 sizes in each group: "Display", "Headline", "Title", "Label" and "Body" which are used across Flet controls. You can now customize each of those styles with page.theme.text_theme, for example:

import flet as ft

def main(page: ft.Page):
page.theme = ft.Theme(
text_theme=ft.TextTheme(body_medium=ft.TextStyle(color=ft.colors.GREEN))
)

page.add(ft.Text("Hello, green world!"))

ft.app(main)

Apparently, Body Medium is used by Text control as a default style.

See TextTheme class for more details.

Tabs themingโ€‹

You can now control the look and feel of Tabs control. In this release Tabs adds a bunch of new properties and there is a new page.theme.tabs_theme property to style all tabs in your app:

page.theme = ft.Theme(
tabs_theme=ft.TabsTheme(
divider_color=ft.colors.BLUE,
indicator_color=ft.colors.RED,
indicator_tab_size=True,
label_color=ft.colors.GREEN,
unselected_label_color=ft.colors.AMBER,
overlay_color={
ft.MaterialState.FOCUSED: ft.colors.with_opacity(0.2, ft.colors.GREEN),
ft.MaterialState.DEFAULT: ft.colors.with_opacity(0.2, ft.colors.PINK),
},
)
)

See TabsTheme class for more details.

Other changesโ€‹

Flutter 3.10โ€‹

This Flet release is based on Flutter 3.10 which brings new features, performance and size optimizations. As a result, most of Flet dependencies bumped their versions too, so if you notice any issues please let us know.

Color emoji in web appsโ€‹

Color emoji support in web apps are back! In Flutter 3.7 color emoji were disabled in "CanvasKit" renderer (default in Flet) because of their font size (8 MB!) and returned back as an opt-in in Flutter 3.10. You can enable color emoji in server-driven app with use_color_emoji argument:

ft.app(main, use_color_emoji=True)

and use --use-color-emoji switch when publishing app as a static side.

That's all for today!

Upgrade Flet module to the latest version (pip install flet --upgrade) and let us know what you think!

Canvas

ยท 3 min read
Feodor Fitsner
Flet founder and developer

Unleash your inner artist ๐Ÿง‘โ€๐ŸŽจ and boost your Flet creativity with brand-new Canvas control just released in Flet 0.6.0!

Canvas enables you to draw arbitrary graphics using a set of primitives, or "shapes", such as line, circle, arc, path and text. I bet you can even implement your own version of charts using Canvas control!

Combine Canvas with GestureDetector and you get a free-hand drawing app - Flet Brush ๐Ÿ˜€!

Example source

Canvas control is located in flet.canvas package. You need another import to use it:

import flet.canvas as cv

Here's a simple program drawing a smiley face with Circle and Arc shapes using filled and stroke Paint:

import math
import flet as ft
import flet.canvas as cv

def main(page: ft.Page):
stroke_paint = paint = ft.Paint(stroke_width=2, style=ft.PaintingStyle.STROKE)
fill_paint = paint = ft.Paint(style=ft.PaintingStyle.FILL)
cp = cv.Canvas(
[
cv.Circle(100, 100, 50, stroke_paint),
cv.Circle(80, 90, 10, stroke_paint),
cv.Circle(84, 87, 5, fill_paint),
cv.Circle(120, 90, 10, stroke_paint),
cv.Circle(124, 87, 5, fill_paint),
cv.Arc(70, 95, 60, 40, 0, math.pi, paint=stroke_paint),
],
width=float("inf"),
expand=True,
)

page.add(cp)

ft.app(main)

Read more about Canvas in docs and explore Canvas examples!

Other changesโ€‹

Rich text supportโ€‹

While working on drawing text on Canvas, as a bonus to this release, we implemented a new TextSpan control which can now be used with Text.spans to output rich text.

Check rich text examples: one, two and three.

url property for buttonsโ€‹

If you need to open a URL by clicking on a button or any other control with on_click event you can just provide that URL in url instead of doing that in the code with page.launch_url() method.

Instead of that:

ft.ElevatedButton("Go to Google", on_click=lambda e: e.page.launch_url("https://google.com"))

you can just do this:

ft.ElevatedButton("Go to Google", url="https://google.com")

A new url property also solves blocked window on Safari issue.

As a continuation of url property Markdown control can now be enabled to auto-follow URLs in the document:

import flet as ft

md = """
[Go to Google](https://www.google.com)
"""

def main(page: ft.Page):
page.add(
ft.Markdown(
md,
extension_set=ft.MarkdownExtensionSet.GITHUB_WEB,
auto_follow_links=True,
)
)

ft.app(main)

Better web supportโ€‹

In this release we also did some improvements to web support like capturing user info in page.client_id and page.client_user_agent as well as fixing nasty #1333 and #1289 bugs related to routing.

That's all for today!

Upgrade Flet module to the latest version (pip install flet --upgrade), give canvas and rich text a try and let us know what you think!

Flet Charts

ยท 2 min read
Feodor Fitsner
Flet founder and developer

Last year we introduced support for Matplotlib and Plotly charts. Both libraries are able to export charts as SVG images which are then displayed in a Flet app. However, such charts, while serving the purpose of visualization, are lacking interactivity and animation.

Today we are releasing Flet 0.5.2 with built-in charts ๐Ÿ“Š based on the awesome fl_chart library!

Three new chart controls have been introduced:

LineChartโ€‹

Docs ยท Examples

BarChartโ€‹

Docs ยท Examples

PieChartโ€‹

Docs ยท Examples

note

We spent a lot of time studying fl_chart library while trying to implement most of its features in a Flet way. However, if you see anything missing in Flet, but available in a library please submit a new feature request.

Other changesโ€‹

Pyodide 0.23โ€‹

Pyodide, which provides Python runtime in a browser and is used to run Flet app as a static website, was upgraded to version 0.23 which is based on Python 3.11.2 and giving some size and performance improvements.

Memory leak fixesโ€‹

In this release we paid a lot of attention to memory leak issues in Flet apps. Now, when a user session is closed its memory is reliably released and garbage-collected. That makes Flet ready for production applications with a lot of users.

Upgrade Flet module to the latest version (pip install flet --upgrade), give charts a try and let us know what you think!

Hey, Flet project has reached โญ๏ธ 5K stars โญ๏ธ - thank you all for your continuing support!