Skip to content

Commit 24f952c

Browse files
authored
CupertinoNavigationBar control (#2241)
* CupertinoNavigationBar * add CupertinoNavigationBar to page * add CupertinoNavigationBar to view * rename active to selected * add docstring * adaptive prop * fix: adaptive prop in wrong file * default value for inactive_color
1 parent b1fbf87 commit 24f952c

File tree

9 files changed

+381
-7
lines changed

9 files changed

+381
-7
lines changed

package/lib/src/controls/create_control.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import 'animated_switcher.dart';
1919
import 'bottom_app_bar.dart';
2020
import 'audio.dart';
2121
import 'badge.dart';
22+
import 'cupertino_navigation_bar.dart';
2223
import 'cupertino_slider.dart';
2324
import 'expansion_panel.dart';
2425
import 'selection_area.dart';
@@ -630,6 +631,13 @@ Widget createWidget(Key? key, ControlViewModel controlView, Control? parent,
630631
children: controlView.children,
631632
parentDisabled: parentDisabled,
632633
dispatch: controlView.dispatch);
634+
case "cupertinonavigationbar":
635+
return CupertinoNavigationBarControl(
636+
parent: parent,
637+
control: controlView.control,
638+
children: controlView.children,
639+
parentDisabled: parentDisabled,
640+
dispatch: controlView.dispatch);
633641
case "bottomappbar":
634642
return BottomAppBarControl(
635643
parent: parent,
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import 'package:collection/collection.dart';
2+
import 'package:flutter/cupertino.dart';
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter_redux/flutter_redux.dart';
5+
6+
import '../actions.dart';
7+
import '../flet_app_services.dart';
8+
import '../models/app_state.dart';
9+
import '../models/control.dart';
10+
import '../models/controls_view_model.dart';
11+
import '../protocol/update_control_props_payload.dart';
12+
import '../utils/colors.dart';
13+
import '../utils/icons.dart';
14+
import 'create_control.dart';
15+
import '../utils/borders.dart';
16+
17+
class CupertinoNavigationBarControl extends StatefulWidget {
18+
final Control? parent;
19+
final Control control;
20+
final List<Control> children;
21+
final bool parentDisabled;
22+
final dynamic dispatch;
23+
24+
const CupertinoNavigationBarControl(
25+
{Key? key,
26+
this.parent,
27+
required this.control,
28+
required this.children,
29+
required this.parentDisabled,
30+
required this.dispatch})
31+
: super(key: key);
32+
33+
@override
34+
State<CupertinoNavigationBarControl> createState() =>
35+
_CupertinoNavigationBarControlState();
36+
}
37+
38+
class _CupertinoNavigationBarControlState
39+
extends State<CupertinoNavigationBarControl> {
40+
int _selectedIndex = 0;
41+
42+
void _onTap(int index) {
43+
_selectedIndex = index;
44+
debugPrint("Selected index: $_selectedIndex");
45+
List<Map<String, String>> props = [
46+
{"i": widget.control.id, "selectedindex": _selectedIndex.toString()}
47+
];
48+
widget.dispatch(
49+
UpdateControlPropsAction(UpdateControlPropsPayload(props: props)));
50+
final server = FletAppServices.of(context).server;
51+
server.updateControlProps(props: props);
52+
server.sendPageEvent(
53+
eventTarget: widget.control.id,
54+
eventName: "change",
55+
eventData: _selectedIndex.toString());
56+
}
57+
58+
@override
59+
Widget build(BuildContext context) {
60+
debugPrint("CupertinoNavigationBarControl build: ${widget.control.id}");
61+
62+
bool disabled = widget.control.isDisabled || widget.parentDisabled;
63+
var selectedIndex = widget.control.attrInt("selectedIndex", 0)!;
64+
65+
if (_selectedIndex != selectedIndex) {
66+
_selectedIndex = selectedIndex;
67+
}
68+
69+
var navBar = StoreConnector<AppState, ControlsViewModel>(
70+
distinct: true,
71+
converter: (store) => ControlsViewModel.fromStore(
72+
store,
73+
widget.children
74+
.where((c) => c.isVisible && c.name == null)
75+
.map((c) => c.id)),
76+
builder: (content, viewModel) {
77+
return CupertinoTabBar(
78+
backgroundColor: HexColor.fromString(
79+
Theme.of(context), widget.control.attrString("bgColor", "")!),
80+
activeColor: HexColor.fromString(
81+
Theme.of(context), widget.control.attrString("activeColor", "")!),
82+
inactiveColor: HexColor.fromString(Theme.of(context),
83+
widget.control.attrString("inactiveColor", "")!) ?? CupertinoColors.inactiveGray,
84+
iconSize: widget.control.attrDouble("iconSize", 30.0)!,
85+
currentIndex: _selectedIndex,
86+
border: parseBorder(Theme.of(context), widget.control, "border"),
87+
onTap: _onTap,
88+
items: viewModel.controlViews.map((destView) {
89+
var label = destView.control.attrString("label", "")!;
90+
91+
var icon =
92+
getMaterialIcon(destView.control.attrString("icon", "")!);
93+
var iconContentCtrls =
94+
destView.children.where((c) => c.name == "icon_content");
95+
96+
var selectedIcon = getMaterialIcon(
97+
destView.control.attrString("selectedIcon", "")!);
98+
var selectedIconContentCtrls = destView.children
99+
.where((c) => c.name == "selected_icon_content");
100+
101+
return BottomNavigationBarItem(
102+
tooltip: destView.control.attrString("tooltip", "")!,
103+
icon: iconContentCtrls.isNotEmpty
104+
? createControl(destView.control,
105+
iconContentCtrls.first.id, disabled)
106+
: Icon(icon),
107+
activeIcon: selectedIconContentCtrls.isNotEmpty
108+
? createControl(destView.control,
109+
selectedIconContentCtrls.first.id, disabled)
110+
: selectedIcon != null
111+
? Icon(selectedIcon)
112+
: null,
113+
label: label);
114+
}).toList());
115+
});
116+
117+
return constrainedControl(context, navBar, widget.parent, widget.control);
118+
}
119+
}

package/lib/src/controls/navigation_bar.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:collection/collection.dart';
2+
import 'package:flutter/foundation.dart';
23
import 'package:flutter/material.dart';
34
import 'package:flutter_redux/flutter_redux.dart';
45

@@ -12,6 +13,7 @@ import '../utils/colors.dart';
1213
import '../utils/icons.dart';
1314
import 'create_control.dart';
1415
import '../utils/borders.dart';
16+
import 'cupertino_navigation_bar.dart';
1517

1618
class NavigationBarControl extends StatefulWidget {
1719
final Control? parent;
@@ -56,6 +58,17 @@ class _NavigationBarControlState extends State<NavigationBarControl> {
5658
Widget build(BuildContext context) {
5759
debugPrint("NavigationBarControl build: ${widget.control.id}");
5860

61+
bool adaptive = widget.control.attrBool("adaptive", false)!;
62+
if (adaptive &&
63+
(defaultTargetPlatform == TargetPlatform.iOS ||
64+
defaultTargetPlatform == TargetPlatform.macOS)) {
65+
return CupertinoNavigationBarControl(
66+
control: widget.control,
67+
children: widget.children,
68+
parentDisabled: widget.parentDisabled,
69+
dispatch: widget.dispatch);
70+
}
71+
5972
bool disabled = widget.control.isDisabled || widget.parentDisabled;
6073
var selectedIndex = widget.control.attrInt("selectedIndex", 0)!;
6174

package/lib/src/controls/page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ class _ViewControlState extends State<ViewControl> {
655655
} else if (ctrl.type == "floatingactionbutton") {
656656
fab = ctrl;
657657
continue;
658-
} else if (ctrl.type == "navigationbar") {
658+
} else if (ctrl.type == "navigationbar" || ctrl.type == "cupertinonavigationbar" ) {
659659
navBar = ctrl;
660660
continue;
661661
} else if (ctrl.type == "navigationdrawer" &&

sdk/python/packages/flet-core/src/flet_core/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
NavigationBarLabelBehavior,
129129
NavigationDestination,
130130
)
131+
from flet_core.cupertino_navigation_bar import CupertinoNavigationBar
131132
from flet_core.navigation_rail import (
132133
NavigationRail,
133134
NavigationRailDestination,

0 commit comments

Comments
 (0)