Skip to content

Commit e07a272

Browse files
CupertinoListTile control (#2487)
* initial commit * leading, title, subtitle, trailing, on_click * additional_info property * bgcolor and bgcolor_activated properties * leading_size and leading_to_title properties * padding property * padding property * clean up * bgcolor to ListTile * adaptive property for ListTile * notched property for CupertinoListTile * toggle_inputs property for CupertinoListTile * clean up * FletControlStatelessMixin * List Tile to use withPagePlatform() --------- Co-authored-by: Feodor Fitsner <[email protected]>
1 parent 1af2e72 commit e07a272

File tree

6 files changed

+563
-70
lines changed

6 files changed

+563
-70
lines changed

package/lib/src/controls/create_control.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import 'container.dart';
3333
import 'cupertino_alert_dialog.dart';
3434
import 'cupertino_checkbox.dart';
3535
import 'cupertino_dialog_action.dart';
36+
import 'cupertino_list_tile.dart';
3637
import 'cupertino_navigation_bar.dart';
3738
import 'cupertino_radio.dart';
3839
import 'cupertino_slider.dart';
@@ -498,6 +499,13 @@ Widget createWidget(Key? key, ControlViewModel controlView, Control? parent,
498499
control: controlView.control,
499500
children: controlView.children,
500501
parentDisabled: parentDisabled);
502+
case "cupertinolisttile":
503+
return CupertinoListTileControl(
504+
key: key,
505+
parent: parent,
506+
control: controlView.control,
507+
children: controlView.children,
508+
parentDisabled: parentDisabled);
501509
case "expansiontile":
502510
return ExpansionTileControl(
503511
key: key,
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import 'package:flutter/cupertino.dart';
2+
import 'package:flutter/material.dart';
3+
4+
import '../models/control.dart';
5+
import '../utils/colors.dart';
6+
import '../utils/edge_insets.dart';
7+
import '../utils/launch_url.dart';
8+
import 'create_control.dart';
9+
import 'flet_control_stateless_mixin.dart';
10+
import 'list_tile.dart';
11+
12+
class CupertinoListTileControl extends StatelessWidget
13+
with FletControlStatelessMixin {
14+
final Control? parent;
15+
final Control control;
16+
final List<Control> children;
17+
final bool parentDisabled;
18+
final ListTileClickNotifier _clickNotifier = ListTileClickNotifier();
19+
20+
CupertinoListTileControl(
21+
{super.key,
22+
this.parent,
23+
required this.control,
24+
required this.children,
25+
required this.parentDisabled});
26+
27+
@override
28+
Widget build(BuildContext context) {
29+
debugPrint("CupertinoListTile build: ${control.id}");
30+
31+
var leadingCtrls =
32+
children.where((c) => c.name == "leading" && c.isVisible);
33+
var titleCtrls = children.where((c) => c.name == "title" && c.isVisible);
34+
var subtitleCtrls =
35+
children.where((c) => c.name == "subtitle" && c.isVisible);
36+
var trailingCtrls =
37+
children.where((c) => c.name == "trailing" && c.isVisible);
38+
var additionalInfoCtrls =
39+
children.where((c) => c.name == "additionalInfo" && c.isVisible);
40+
41+
bool notched = control.attrBool("notched", false)!;
42+
bool onclick = control.attrBool("onclick", false)!;
43+
bool toggleInputs = control.attrBool("toggleInputs", false)!;
44+
String url = control.attrString("url", "")!;
45+
String? urlTarget = control.attrString("urlTarget");
46+
bool disabled = control.isDisabled || parentDisabled;
47+
48+
Widget? additionalInfo = additionalInfoCtrls.isNotEmpty
49+
? createControl(control, additionalInfoCtrls.first.id, disabled)
50+
: null;
51+
Widget? leading = leadingCtrls.isNotEmpty
52+
? createControl(control, leadingCtrls.first.id, disabled)
53+
: null;
54+
55+
Widget? title = titleCtrls.isNotEmpty
56+
? createControl(control, titleCtrls.first.id, disabled)
57+
: const Text("");
58+
59+
Widget? subtitle = subtitleCtrls.isNotEmpty
60+
? createControl(control, subtitleCtrls.first.id, disabled)
61+
: null;
62+
63+
Widget? trailing = trailingCtrls.isNotEmpty
64+
? createControl(control, trailingCtrls.first.id, disabled)
65+
: null;
66+
67+
Color? backgroundColor = HexColor.fromString(
68+
Theme.of(context), control.attrString("bgcolor", "")!);
69+
Color? bgcolorActivated = HexColor.fromString(
70+
Theme.of(context), control.attrString("bgcolorActivated", "")!);
71+
72+
var padding = parseEdgeInsets(control, "contentPadding");
73+
74+
Function()? onPressed = (onclick || toggleInputs || url != "") && !disabled
75+
? () {
76+
debugPrint("CupertinoListTile ${control.id} clicked!");
77+
if (toggleInputs) {
78+
_clickNotifier.onClick();
79+
}
80+
if (url != "") {
81+
openWebBrowser(url, webWindowName: urlTarget);
82+
}
83+
if (onclick) {
84+
sendControlEvent(context, control.id, "click", "");
85+
}
86+
}
87+
: null;
88+
89+
Widget tile;
90+
!notched
91+
? tile = CupertinoListTile(
92+
onTap: onPressed,
93+
additionalInfo: additionalInfo,
94+
backgroundColor: backgroundColor,
95+
backgroundColorActivated: bgcolorActivated,
96+
leading: leading,
97+
leadingSize: control.attrDouble("leadingSize", 28.0)!,
98+
leadingToTitle: control.attrDouble("leadingToTitle", 16.0)!,
99+
padding: padding,
100+
title: title,
101+
subtitle: subtitle,
102+
trailing: trailing,
103+
)
104+
: tile = CupertinoListTile.notched(
105+
onTap: onPressed,
106+
additionalInfo: additionalInfo,
107+
backgroundColor: backgroundColor,
108+
backgroundColorActivated: bgcolorActivated,
109+
leading: leading,
110+
padding: padding,
111+
title: title,
112+
subtitle: subtitle,
113+
trailing: trailing,
114+
);
115+
116+
if (toggleInputs) {
117+
tile = ListTileClicks(notifier: _clickNotifier, child: tile);
118+
}
119+
120+
return constrainedControl(context, tile, parent, control);
121+
}
122+
}

package/lib/src/controls/list_tile.dart

Lines changed: 91 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import 'package:flutter/material.dart';
22

33
import '../models/control.dart';
4+
import '../utils/colors.dart';
45
import '../utils/edge_insets.dart';
56
import '../utils/launch_url.dart';
67
import 'create_control.dart';
8+
import 'cupertino_list_tile.dart';
79
import 'flet_control_stateless_mixin.dart';
10+
import 'flet_store_mixin.dart';
811

912
class ListTileClicks extends InheritedWidget {
1013
const ListTileClicks({
@@ -23,7 +26,8 @@ class ListTileClicks extends InheritedWidget {
2326
bool updateShouldNotify(ListTileClicks oldWidget) => true;
2427
}
2528

26-
class ListTileControl extends StatelessWidget with FletControlStatelessMixin {
29+
class ListTileControl extends StatelessWidget
30+
with FletControlStatelessMixin, FletStoreMixin {
2731
final Control? parent;
2832
final Control control;
2933
final List<Control> children;
@@ -40,76 +44,93 @@ class ListTileControl extends StatelessWidget with FletControlStatelessMixin {
4044
@override
4145
Widget build(BuildContext context) {
4246
debugPrint("ListTile build: ${control.id}");
43-
44-
var leadingCtrls =
45-
children.where((c) => c.name == "leading" && c.isVisible);
46-
var titleCtrls = children.where((c) => c.name == "title" && c.isVisible);
47-
var subtitleCtrls =
48-
children.where((c) => c.name == "subtitle" && c.isVisible);
49-
var trailingCtrls =
50-
children.where((c) => c.name == "trailing" && c.isVisible);
51-
52-
bool selected = control.attrBool("selected", false)!;
53-
bool dense = control.attrBool("dense", false)!;
54-
bool isThreeLine = control.attrBool("isThreeLine", false)!;
55-
bool autofocus = control.attrBool("autofocus", false)!;
56-
bool onclick = control.attrBool("onclick", false)!;
57-
bool toggleInputs = control.attrBool("toggleInputs", false)!;
58-
bool onLongPressDefined = control.attrBool("onLongPress", false)!;
59-
String url = control.attrString("url", "")!;
60-
String? urlTarget = control.attrString("urlTarget");
61-
bool disabled = control.isDisabled || parentDisabled;
62-
63-
Function()? onPressed = (onclick || toggleInputs || url != "") && !disabled
64-
? () {
65-
debugPrint("ListTile ${control.id} clicked!");
66-
if (toggleInputs) {
67-
_clickNotifier.onClick();
68-
}
69-
if (url != "") {
70-
openWebBrowser(url, webWindowName: urlTarget);
71-
}
72-
if (onclick) {
73-
sendControlEvent(context, control.id, "click", "");
47+
return withPagePlatform((context, platform) {
48+
bool adaptive = control.attrBool("adaptive", false)!;
49+
if (adaptive &&
50+
(platform == TargetPlatform.iOS ||
51+
platform == TargetPlatform.macOS)) {
52+
return CupertinoListTileControl(
53+
control: control,
54+
parent: parent,
55+
parentDisabled: parentDisabled,
56+
children: children);
57+
}
58+
59+
var leadingCtrls =
60+
children.where((c) => c.name == "leading" && c.isVisible);
61+
var titleCtrls = children.where((c) => c.name == "title" && c.isVisible);
62+
var subtitleCtrls =
63+
children.where((c) => c.name == "subtitle" && c.isVisible);
64+
var trailingCtrls =
65+
children.where((c) => c.name == "trailing" && c.isVisible);
66+
67+
bool selected = control.attrBool("selected", false)!;
68+
bool dense = control.attrBool("dense", false)!;
69+
bool isThreeLine = control.attrBool("isThreeLine", false)!;
70+
bool autofocus = control.attrBool("autofocus", false)!;
71+
bool onclick = control.attrBool("onclick", false)!;
72+
bool toggleInputs = control.attrBool("toggleInputs", false)!;
73+
bool onLongPressDefined = control.attrBool("onLongPress", false)!;
74+
String url = control.attrString("url", "")!;
75+
String? urlTarget = control.attrString("urlTarget");
76+
bool disabled = control.isDisabled || parentDisabled;
77+
78+
Function()? onPressed =
79+
(onclick || toggleInputs || url != "") && !disabled
80+
? () {
81+
debugPrint("ListTile ${control.id} clicked!");
82+
if (toggleInputs) {
83+
_clickNotifier.onClick();
84+
}
85+
if (url != "") {
86+
openWebBrowser(url, webWindowName: urlTarget);
87+
}
88+
if (onclick) {
89+
sendControlEvent(context, control.id, "click", "");
90+
}
91+
}
92+
: null;
93+
94+
Function()? onLongPress = onLongPressDefined && !disabled
95+
? () {
96+
debugPrint("Button ${control.id} clicked!");
97+
sendControlEvent(context, control.id, "long_press", "");
7498
}
75-
}
76-
: null;
77-
78-
Function()? onLongPress = onLongPressDefined && !disabled
79-
? () {
80-
debugPrint("Button ${control.id} clicked!");
81-
sendControlEvent(context, control.id, "long_press", "");
82-
}
83-
: null;
84-
85-
Widget tile = ListTile(
86-
autofocus: autofocus,
87-
contentPadding: parseEdgeInsets(control, "contentPadding"),
88-
isThreeLine: isThreeLine,
89-
selected: selected,
90-
dense: dense,
91-
onTap: onPressed,
92-
onLongPress: onLongPress,
93-
enabled: !disabled,
94-
leading: leadingCtrls.isNotEmpty
95-
? createControl(control, leadingCtrls.first.id, disabled)
96-
: null,
97-
title: titleCtrls.isNotEmpty
98-
? createControl(control, titleCtrls.first.id, disabled)
99-
: null,
100-
subtitle: subtitleCtrls.isNotEmpty
101-
? createControl(control, subtitleCtrls.first.id, disabled)
102-
: null,
103-
trailing: trailingCtrls.isNotEmpty
104-
? createControl(control, trailingCtrls.first.id, disabled)
105-
: null,
106-
);
107-
108-
if (toggleInputs) {
109-
tile = ListTileClicks(notifier: _clickNotifier, child: tile);
110-
}
111-
112-
return constrainedControl(context, tile, parent, control);
99+
: null;
100+
101+
Widget tile = ListTile(
102+
autofocus: autofocus,
103+
contentPadding: parseEdgeInsets(control, "contentPadding"),
104+
isThreeLine: isThreeLine,
105+
selected: selected,
106+
dense: dense,
107+
onTap: onPressed,
108+
onLongPress: onLongPress,
109+
enabled: !disabled,
110+
tileColor: HexColor.fromString(
111+
Theme.of(context), control.attrString("bgcolor", "")!),
112+
splashColor: HexColor.fromString(
113+
Theme.of(context), control.attrString("bgcolorActivated", "")!),
114+
leading: leadingCtrls.isNotEmpty
115+
? createControl(control, leadingCtrls.first.id, disabled)
116+
: null,
117+
title: titleCtrls.isNotEmpty
118+
? createControl(control, titleCtrls.first.id, disabled)
119+
: null,
120+
subtitle: subtitleCtrls.isNotEmpty
121+
? createControl(control, subtitleCtrls.first.id, disabled)
122+
: null,
123+
trailing: trailingCtrls.isNotEmpty
124+
? createControl(control, trailingCtrls.first.id, disabled)
125+
: null,
126+
);
127+
128+
if (toggleInputs) {
129+
tile = ListTileClicks(notifier: _clickNotifier, child: tile);
130+
}
131+
132+
return constrainedControl(context, tile, parent, control);
133+
});
113134
}
114135
}
115136

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
from flet_core.cupertino_app_bar import CupertinoAppBar
6969
from flet_core.cupertino_checkbox import CupertinoCheckbox
7070
from flet_core.cupertino_dialog_action import CupertinoDialogAction
71+
from flet_core.cupertino_list_tile import CupertinoListTile
7172
from flet_core.cupertino_navigation_bar import CupertinoNavigationBar
7273
from flet_core.cupertino_radio import CupertinoRadio
7374
from flet_core.cupertino_slider import CupertinoSlider

0 commit comments

Comments
 (0)