-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathappbar.py
172 lines (137 loc) · 5.15 KB
/
appbar.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import flet
from flet import AppBar
from flet import Card
from flet import Column
from flet import Container
from flet import Icon
from flet import IconButton
from flet import NavigationRail
from flet import NavigationRailDestination
from flet import Page
from flet import Row
from flet import Stack
from flet import Text
from flet import UserControl
from flet import VerticalDivider
from flet import colors
from flet import icons
class ResponsiveMenuLayout(Row):
def __init__(self, page, pages, *args, **kwargs):
super().__init__(*args, **kwargs)
self.expand = True
self.page = page
self.pages = pages
navigation_items = [navigation_item for navigation_item, _ in pages]
self.navigation_rail = self._build_navigation_rail(navigation_items)
page_contents = [page_content for _, page_content in pages]
self.menu_panel = Row(
controls=[self.navigation_rail, VerticalDivider(width=1)],
spacing=0,
)
self.content_area = Column(page_contents, expand=True)
self._was_portrait = self.is_portrait()
self._panel_visible = self.is_landscape()
self.set_navigation_content()
self._change_displayed_page()
self.page.on_resize = self.handle_resize
def select_page(self, page_number):
self.navigation_rail.selected_index = page_number
self._change_displayed_page()
def _navigation_change(self, e):
self._change_displayed_page()
def _change_displayed_page(self):
selected_index = self.navigation_rail.selected_index
# page_contents = [page_content for _, page_content in self.pages]
for i, content_page in enumerate(self.content_area.controls):
content_page.visible = selected_index == i
self.check_toggle_on_select()
self.page.update()
def _build_navigation_rail(self, navigation_items):
return NavigationRail(
selected_index=0,
label_type="all",
extended=True,
destinations=navigation_items,
on_change=self._navigation_change,
)
def handle_resize(self, e):
if self._was_portrait != self.is_portrait():
self._was_portrait = self.is_portrait()
self._panel_visible = self.is_landscape()
self.set_navigation_content()
self.page.update()
def toggle_navigation(self):
self._panel_visible = not self._panel_visible
self.set_navigation_content()
self.page.update()
def check_toggle_on_select(self):
if self.is_portrait() and self._panel_visible:
self.toggle_navigation()
def set_navigation_content(self):
if self.is_landscape():
self.add_landscape_content()
else:
self.add_portrait_content()
def add_landscape_content(self):
self.controls = [self.menu_panel, self.content_area]
self.menu_panel.visible = self._panel_visible
def add_portrait_content(self):
self.controls = [Stack(controls=[self.content_area, self.menu_panel], expand=True)]
self.menu_panel.visible = self._panel_visible
def is_portrait(self) -> bool:
# Return true if window/display is narrow
return self.page.window_height >= self.page.window_width
def is_landscape(self) -> bool:
# Return true if window/display is wide
return self.page.window_width > self.page.window_height
def main(page: Page, title="Basic Responsive Menu"):
page.title = title
menu_button = IconButton(icons.MENU)
page.appbar = AppBar(
leading=menu_button,
leading_width=40,
title=Text(title),
bgcolor=colors.SURFACE_VARIANT,
)
pages = [
(
NavigationRailDestination(
icon=icons.LANDSCAPE_OUTLINED, selected_icon=icons.LANDSCAPE, label="Menu in landscape"
),
create_page(
"Menu in landscape",
"Menu in landscape is by default shown, side by side with the main content, but can be "
"hidden with the menu button.",
),
),
(
NavigationRailDestination(
icon=icons.PORTRAIT_OUTLINED,
selected_icon=icons.PORTRAIT,
label="Menu in portrait",
),
create_page(
"Menu in portrait",
"Menu in portrait is mainly expected to be used on a smaller mobile device. The menu is by default "
"hidden, and when shown with the menu button it is placed on top of the main content.",
),
),
]
menu_layout = ResponsiveMenuLayout(page, pages)
page.add(menu_layout)
menu_button.on_click = lambda e: menu_layout.toggle_navigation()
def create_page(title: str, body: str):
return Row(
controls=[
Column(
horizontal_alignment="stretch",
controls=[
Card(content=Container(Text(title, weight="bold"), padding=8)),
Text(body),
],
expand=True,
),
],
expand=True,
)
flet.app(target=main)