Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions packages/flet/lib/src/controls/bottom_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,35 @@ class BottomAppBarControl extends StatelessWidget {
Widget build(BuildContext context) {
debugPrint("BottomAppBarControl build: ${control.id}");

var bottomAppBar = BottomAppBar(
clipBehavior: control.getClipBehavior("clip_behavior", Clip.none)!,
final theme = Theme.of(context);
var borderRadius = control.getBorderRadius("border_radius");
final clipBehavior = control.getClipBehavior(
"clip_behavior",
borderRadius != null && borderRadius != BorderRadius.zero
? Clip.antiAlias
: Clip.none)!;

Widget bottomAppBar = BottomAppBar(
clipBehavior: clipBehavior,
padding: control.getPadding("padding"),
height: control.getDouble("height"),
elevation: control.getDouble("elevation"),
shape: control.getNotchedShape("shape", Theme.of(context)),
shape: control.getNotchedShape("shape", theme),
shadowColor: control.getColor("shadow_color", context),
color: control.getColor("bgcolor", context),
notchMargin: control.getDouble("notch_margin", 4.0)!,
child: control.buildWidget("content"),
);

if (borderRadius != null && borderRadius != BorderRadius.zero) {
bottomAppBar = ClipRRect(
borderRadius: borderRadius,
// can't use Clip.none here, so fallback to Clip.antiAlias in that case
clipBehavior: clipBehavior == Clip.none ? Clip.antiAlias : clipBehavior,
child: bottomAppBar,
);
}

return LayoutControl(control: control, child: bottomAppBar);
}
}
Empty file.
25 changes: 25 additions & 0 deletions sdk/python/examples/controls/bottom_app_bar/border_radius.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import flet as ft


def main(page: ft.Page):
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER

page.bottom_appbar = ft.BottomAppBar(
border_radius=ft.BorderRadius.all(20),
bgcolor=ft.Colors.BLUE,
content=ft.Row(
controls=[
ft.IconButton(icon=ft.Icons.MENU, icon_color=ft.Colors.WHITE),
ft.Container(expand=True),
ft.IconButton(icon=ft.Icons.SEARCH, icon_color=ft.Colors.WHITE),
ft.IconButton(icon=ft.Icons.FAVORITE, icon_color=ft.Colors.WHITE),
]
),
)

page.add(ft.Text("Content goes here..."))


if __name__ == "__main__":
ft.run(main)
Binary file not shown.
11 changes: 3 additions & 8 deletions sdk/python/examples/controls/bottom_app_bar/notched_fab.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ def main(page: ft.Page):
)
page.floating_action_button_location = ft.FloatingActionButtonLocation.CENTER_DOCKED

page.appbar = ft.AppBar(
title=ft.Text("Bottom AppBar Demo"),
center_title=True,
bgcolor=ft.Colors.GREEN_300,
automatically_imply_leading=False,
)
page.bottom_appbar = ft.BottomAppBar(
bgcolor=ft.Colors.BLUE,
shape=ft.CircularRectangleNotchShape(),
Expand All @@ -30,7 +24,8 @@ def main(page: ft.Page):
),
)

page.add(ft.Text("Body!"))
page.add(ft.Text("Content goes here..."))


ft.run(main)
if __name__ == "__main__":
ft.run(main)
10 changes: 8 additions & 2 deletions sdk/python/packages/flet/docs/controls/bottomappbar.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
class_name: flet.BottomAppBar
examples: ../../examples/controls/bottom_app_bar
example_images: ../test-images/examples/material/golden/macos/bottom_app_bar
example_media: ../examples/controls/bottom_app_bar/media
---

{{ class_summary(class_name, example_images + "/image_for_docs.png", image_caption="Basic BottomAppBar", image_width="100%") }}
Expand All @@ -17,7 +16,14 @@ example_media: ../examples/controls/bottom_app_bar/media
--8<-- "{{ examples }}/notched_fab.py"
```

{{ image(example_media + "/notched_fab.png", alt="notched-fab", width="80%") }}
{{ image(example_images + "/notched_fab.png", width="80%") }}

### Custom border radius

```python
--8<-- "{{ examples }}/border_radius.py"
```

{{ image(example_images + "/border_radius.png", width="80%") }}

{{ class_members(class_name) }}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,69 @@

import flet as ft
import flet.testing as ftt
from examples.controls.bottom_app_bar import border_radius, notched_fab


@pytest.mark.asyncio(loop_scope="function")
async def test_image_for_docs(flet_app_function: ftt.FletTestApp, request):
flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT
flet_app_function.page.window.width = 400

await flet_app_function.assert_control_screenshot(
request.node.name,
ft.BottomAppBar(
bgcolor=ft.Colors.SURFACE_CONTAINER_LOW,
content=ft.Row(
alignment=ft.MainAxisAlignment.SPACE_AROUND,
controls=[
ft.IconButton(ft.Icons.MENU),
ft.IconButton(ft.Icons.SEARCH),
ft.IconButton(ft.Icons.SETTINGS),
],
alignment=ft.MainAxisAlignment.SPACE_AROUND,
),
),
)


@pytest.mark.parametrize(
"flet_app_function",
[{"flet_app_main": border_radius.main}],
indirect=True,
)
@pytest.mark.asyncio(loop_scope="function")
async def test_border_radius(flet_app_function: ftt.FletTestApp):
flet_app_function.page.enable_screenshots = True
flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT
flet_app_function.page.window.width = 500
flet_app_function.page.window.height = 400
flet_app_function.page.update()

await flet_app_function.tester.pump_and_settle()
flet_app_function.assert_screenshot(
"border_radius",
await flet_app_function.page.take_screenshot(
pixel_ratio=flet_app_function.screenshots_pixel_ratio
),
)


@pytest.mark.parametrize(
"flet_app_function",
[{"flet_app_main": notched_fab.main}],
indirect=True,
)
@pytest.mark.asyncio(loop_scope="function")
async def test_notched_fab(flet_app_function: ftt.FletTestApp):
flet_app_function.page.enable_screenshots = True
flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT
flet_app_function.page.window.width = 500
flet_app_function.page.window.height = 400
flet_app_function.page.update()

await flet_app_function.tester.pump_and_settle()
flet_app_function.assert_screenshot(
"notched_fab",
await flet_app_function.page.take_screenshot(
pixel_ratio=flet_app_function.screenshots_pixel_ratio
),
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async def test_image_for_docs(flet_app_function: ftt.FletTestApp, request):
flet_app_function.page.update()
await flet_app_function.tester.pump_and_settle()
flet_app_function.assert_screenshot(
"test_image_for_docs",
request.node.name,
await flet_app_function.page.take_screenshot(
pixel_ratio=flet_app_function.screenshots_pixel_ratio
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Optional

from flet.controls.base_control import control
from flet.controls.border_radius import BorderRadiusValue
from flet.controls.control import Control
from flet.controls.layout_control import LayoutControl
from flet.controls.padding import PaddingValue
Expand All @@ -23,12 +24,12 @@ class BottomAppBar(LayoutControl):
ft.BottomAppBar(
bgcolor=ft.Colors.SURFACE_CONTAINER_LOW,
content=ft.Row(
alignment=ft.MainAxisAlignment.SPACE_AROUND,
controls=[
ft.IconButton(ft.Icons.MENU),
ft.IconButton(ft.Icons.SEARCH),
ft.IconButton(ft.Icons.SETTINGS),
],
alignment=ft.MainAxisAlignment.SPACE_AROUND,
),
)
```
Expand All @@ -43,47 +44,69 @@ class BottomAppBar(LayoutControl):
"""
The fill color to use for this app bar.
Defaults to [`BottomAppBarTheme.bgcolor`][flet.], or if
that is `None`, falls back to [`ColorScheme.surface`][flet.].
If `None`, [`BottomAppBarTheme.bgcolor`][flet.] is used;
if that is also `None`, then defaults to [`ColorScheme.surface`][flet.].
"""

shadow_color: Optional[ColorValue] = None
"""
The color of the shadow below this app bar.
If `None`, [`BottomAppBarTheme.shadow_color`][flet.] is used;
if that is also `None`, then defaults to [`Colors.TRANSPARENT`][flet.].
"""

padding: Optional[PaddingValue] = None
"""
Empty space to inscribe inside a container decoration (background, border).
Defaults to [`BottomAppBarTheme.padding`][flet.], or if
that is `None`, falls back to `Padding.symmetric(vertical=12.0, horizontal=16.0)`.
If `None`, [`BottomAppBarTheme.padding`][flet.] is used;
if that is also `None`, then defaults to
`Padding.symmetric(vertical=12.0, horizontal=16.0)`.
"""

clip_behavior: ClipBehavior = ClipBehavior.NONE
clip_behavior: Optional[ClipBehavior] = None
"""
Defines how the [`content`][(c).] of this app bar should be clipped.
If `None`, defaults to:
- [`ClipBehavior.ANTI_ALIAS`][flet.] if [`border_radius`][(c).]
is set and not equal to [`BorderRadius.all(0)`][flet.BorderRadius.all];
- Else [`ClipBehavior.NONE`][flet.].
"""

shape: Optional[NotchShape] = None
"""
The notch that is made for the floating action button.
If `None`, [`BottomAppBarTheme.shape`][flet.] is used;
if that is also `None`, then the shape will be rectangular with no notch.
"""

notch_margin: Number = 4.0
"""
The margin between the [`FloatingActionButton`][flet.] and this
app bar's notch.
Can be visible only if [`shape`][(c).] is `None`.
Note:
Has effect only if [`shape`][(c).] is not `None`.
"""

elevation: Optional[Number] = None
"""
This property controls the size of the shadow below this app bar.
The z-coordinate at which to place this bottom app bar relative to its
parent. It controls the size of the shadow below this app bar.
If `None`, [`BottomAppBarTheme.elevation`][flet.] is used;
if that is also `None`, then defaults to `3`.
Raises:
ValueError: If [`elevation`][(c).] is negative.
ValueError: If it is less than `0`.
"""

border_radius: Optional[BorderRadiusValue] = None
"""
The border radius to apply when clipping and painting this app bar.
"""

def before_update(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class FloatingActionButton(LayoutControl):
The content of this button.

Raises:
ValueError: If neither [`icon`][(c).] nor a valid [`content`][(c).]
ValueError: If neither [`icon`][(c).] nor a valid `content`
(string or visible Control) is provided.
"""

Expand Down Expand Up @@ -95,7 +95,7 @@ class FloatingActionButton(LayoutControl):
Defaults to `6`.

Raises:
ValueError: If [`elevation`][(c).] is negative.
ValueError: If it is less than `0`.
"""

disabled_elevation: Optional[Number] = None
Expand All @@ -105,7 +105,7 @@ class FloatingActionButton(LayoutControl):
Defaults to the same value as `elevation`.

Raises:
ValueError: If [`disabled_elevation`][(c).] is negative.
ValueError: If it is less than `0`.
"""

focus_elevation: Optional[Number] = None
Expand All @@ -115,7 +115,7 @@ class FloatingActionButton(LayoutControl):
Defaults to `8`.

Raises:
ValueError: If [`focus_elevation`][(c).] is negative.
ValueError: If it is less than `0`.
"""

highlight_elevation: Optional[Number] = None
Expand All @@ -125,7 +125,7 @@ class FloatingActionButton(LayoutControl):
Defaults to `12`.

Raises:
ValueError: If [`highlight_elevation`][(c).] is negative.
ValueError: If it is less than `0`.
"""

hover_elevation: Optional[Number] = None
Expand All @@ -135,7 +135,7 @@ class FloatingActionButton(LayoutControl):
Defaults to `8`.

Raises:
ValueError: If [`hover_elevation`][(c).] is negative.
ValueError: If it is less than `0`.
"""

hover_color: Optional[ColorValue] = None
Expand Down
Loading