はじめに
Fletの公式サイトにアイコン検索ができるサイトがあるのですが、いつの間にか使えなくなっていました。(2/2現在)
恐らくメモリ不足になっているのではないかと思います。
サイト:https://flet-icons-browser.fly.dev/#/
そこで、公開されているソースをもとに少し改良したものを作ってみたので、その内容をまとめておきます。
公式のソース:https://github.com/flet-dev/examples/tree/main/python/apps/icons-browser
ちなみにアイコンの検索は↓できます。(たぶんFlutter用を探せば使える)
https://fonts.google.com/icons?selected=Material+Icons&icon.platform=flutter&icon.set=Material+Icons
2023/2/4 に公式サイトの変更があったようです。
いまはアイコン検索のURLが↓になっていて動きます。
https://flet-icons-browser.pages.dev/
作ったもの
作ったアイコンブラウザはこちら。良ければ試してみてください。
改良ポイント
- googleを参考に4分類して検索するようにした
- 確かに4種類を一緒に出す必要もないと思うのでそうした
- これにより、全アイコン表示しても2千ほどになって軽くなった
- fly.ioでメモリ不足にもならなくなった
- DARKモードの表示も見れるようにSwitchを追加した
- page.theme_modeを変えてるだけ
- 検索文字列なしの時は全部のアイコンを表示するようにした
- サンプルだとこれができなかった
- 目視になるけど全体を見れるのは個人的には必要
経緯まとめ
- 公式サイトのアイコンブラウザを使おうとしたら使えなかった(応答がない状況)
- しょうがないので、公開されているソースをローカルで動かしてみる
- なんか使い勝手がいまいちなので改良してみることに
- サンプルソースがyieldを使ってややこしいつくりになっているのを確認
- 全部のアイコンが見れないのが嫌だったのでその辺を変更
- アイコンを大量に表示すると結構遅いけどローカルでは動くのを確認
- fly.ioにアップしたらメモリ不足で動かないことを確認(サンプルでyieldを使っているのはこのためか?)
- 中身はFlutterなので、Flutterのアイコンを検索
- これを発見 https://fonts.google.com/icons?selected=Material+Icons&icon.platform=flutter&icon.set=Material+Icons
- ↑を参考にさらに改良
- 改良によってfly.ioでも動くようになった
ソース
ソースはこちら。
150行程度でここまでできるのは楽だと思います。
import flet as ft
class IconBrowser(ft.UserControl):
def __init__(self, expand=False, height=500):
super().__init__()
if expand:
self.expand = expand
else:
self.height = height
def build(self):
def copy_to_clipboard(e):
icon_key = e.control.data
print("Copy to clipboard:", icon_key)
self.page.set_clipboard(e.control.data)
self.page.show_snack_bar(
ft.SnackBar(ft.Text(f"Copied {icon_key}"), open=True))
def search_icons(type: str, search_term: str):
if self.page != None:
search_results.clean()
count = 0
for icon_name in icons_list:
icon_key = f"icons.{icon_name.upper()}"
if type == "" \
and ("OUTLINED" in icon_key or
"ROUNDED" in icon_key or
"SHARP" in icon_key):
# Filledは↑の文字列を含む場合はスキップ
continue
elif type not in icon_key:
# タイプの文字列を含まない場合はスキップ
continue
if search_term.upper() not in icon_key:
# 入力値を含まない場合はスキップ
continue
search_results.controls.append(
ft.TextButton(
content=ft.Container(ft.Column(
[
ft.Icon(name=icon_name),
ft.Text(
value=f"{icon_name}",
size=12,
width=120,
no_wrap=True,
text_align="center",
color=ft.colors.ON_SURFACE_VARIANT,
),
],
spacing=0,
alignment="center",
horizontal_alignment="center",
),
alignment=ft.alignment.center,
),
tooltip=f"{icon_key}\nClick to copy to a clipboard",
on_click=copy_to_clipboard,
data=icon_key,
)
)
count += 1
if self.page != None:
message = f"{count} icons found"
if count == 0:
message = "No icons found"
self.page.show_snack_bar(
ft.SnackBar(ft.Text(message), open=True))
self.update()
def change_theme_mode(e: ft.UserControl):
value = e.control.value
if value:
self.page.theme_mode = ft.ThemeMode.DARK
else:
self.page.theme_mode = ft.ThemeMode.LIGHT
self.page.update()
# fetch all icon constants from icons.py module
icons_list = []
list_started = False
for key, value in vars(ft.icons).items():
if key == "TEN_K":
list_started = True
if list_started:
icons_list.append(value)
# I/O Controls
search_txt = ft.TextField(
expand=1,
hint_text="Enter keyword and press search button",
autofocus=True,
on_submit=lambda _: search_icons(
select_type_group.value, search_txt.value),
)
search_query = ft.Row([
search_txt,
ft.IconButton(icon=ft.icons.SEARCH,
on_click=lambda _: search_icons(
select_type_group.value, search_txt.value))
])
select_type_group = ft.RadioGroup(
ft.Row([
ft.Radio(label="Outlined", value="OUTLINED"),
ft.Radio(label="Filled", value=""),
ft.Radio(label="Rounded", value="ROUNDED"),
ft.Radio(label="Sharp", value="SHARP"),
]),
value="OUTLINED",
on_change=lambda _: search_icons(
select_type_group.value, search_txt.value),
)
select_type = ft.Row([
select_type_group
])
select_theme_mode = ft.Row([
ft.Switch(
label="DARK",
on_change=change_theme_mode
)
])
search_results = ft.GridView(
expand=1,
runs_count=10,
max_extent=120,
run_spacing=0,
child_aspect_ratio=1,
)
status_bar = ft.Text()
search_icons(select_type_group.value, search_txt.value)
return ft.Column(
[
search_query,
select_type,
select_theme_mode,
search_results,
status_bar,
],
expand=True,
)
def main(page: ft.Page):
page.theme_mode = ft.ThemeMode.LIGHT
page.title = "My Flet icons browser"
page.add(IconBrowser(expand=True))
ft.flet.app(target=main)