diff --git a/packages/flet/lib/src/controls/list_view.dart b/packages/flet/lib/src/controls/list_view.dart index 768f9f9f7..d1f51d248 100644 --- a/packages/flet/lib/src/controls/list_view.dart +++ b/packages/flet/lib/src/controls/list_view.dart @@ -52,22 +52,27 @@ class _ListViewControlState extends State { bool? adaptive = widget.control.attrBool("adaptive") ?? widget.parentAdaptive; - final horizontal = widget.control.attrBool("horizontal", false)!; - final spacing = widget.control.attrDouble("spacing", 0)!; - final dividerThickness = widget.control.attrDouble("dividerThickness", 0)!; - final itemExtent = widget.control.attrDouble("itemExtent"); - final cacheExtent = widget.control.attrDouble("cacheExtent"); - final semanticChildCount = widget.control.attrInt("semanticChildCount"); - final firstItemPrototype = + var horizontal = widget.control.attrBool("horizontal", false)!; + var spacing = widget.control.attrDouble("spacing", 0)!; + var dividerThickness = widget.control.attrDouble("dividerThickness", 0)!; + var itemExtent = widget.control.attrDouble("itemExtent"); + var cacheExtent = widget.control.attrDouble("cacheExtent"); + var semanticChildCount = widget.control.attrInt("semanticChildCount"); + var firstItemPrototype = widget.control.attrBool("firstItemPrototype", false)!; - final padding = parseEdgeInsets(widget.control, "padding"); - final reverse = widget.control.attrBool("reverse", false)!; + var padding = parseEdgeInsets(widget.control, "padding"); + var reverse = widget.control.attrBool("reverse", false)!; var clipBehavior = parseClip(widget.control.attrString("clipBehavior"), Clip.hardEdge)!; - List visibleControls = - widget.children.where((c) => c.isVisible).toList(); + List ctrls = widget.children.where((c) => c.isVisible).toList(); var scrollDirection = horizontal ? Axis.horizontal : Axis.vertical; + var buildControlsOnDemand = + widget.control.attrBool("buildControlsOnDemand", true)!; + var prototypeItem = firstItemPrototype && widget.children.isNotEmpty + ? createControl(widget.control, ctrls[0].id, disabled, + parentAdaptive: adaptive) + : null; Widget listView = LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -77,9 +82,8 @@ class _ListViewControlState extends State { var shrinkWrap = (!horizontal && constraints.maxHeight == double.infinity) || (horizontal && constraints.maxWidth == double.infinity); - - Widget child = spacing > 0 - ? ListView.separated( + Widget child = !buildControlsOnDemand + ? ListView( controller: _controller, cacheExtent: cacheExtent, reverse: reverse, @@ -87,46 +91,59 @@ class _ListViewControlState extends State { scrollDirection: scrollDirection, shrinkWrap: shrinkWrap, padding: padding, - itemCount: widget.children.length, - itemBuilder: (context, index) { - return createControl( - widget.control, visibleControls[index].id, disabled, - parentAdaptive: adaptive); - }, - separatorBuilder: (context, index) { - return horizontal - ? dividerThickness == 0 - ? SizedBox(width: spacing) - : VerticalDivider( - width: spacing, thickness: dividerThickness) - : dividerThickness == 0 - ? SizedBox(height: spacing) - : Divider( - height: spacing, thickness: dividerThickness); - }, - ) - : ListView.builder( - controller: _controller, - clipBehavior: clipBehavior, semanticChildCount: semanticChildCount, - reverse: reverse, - cacheExtent: cacheExtent, - scrollDirection: scrollDirection, - shrinkWrap: shrinkWrap, - padding: padding, - itemCount: widget.children.length, itemExtent: itemExtent, - itemBuilder: (context, index) { - return createControl( - widget.control, visibleControls[index].id, disabled, - parentAdaptive: adaptive); - }, - prototypeItem: firstItemPrototype && widget.children.isNotEmpty - ? createControl( - widget.control, visibleControls[0].id, disabled, - parentAdaptive: adaptive) - : null, - ); + children: ctrls + .map((c) => createControl(widget.control, c.id, disabled, + parentAdaptive: adaptive)) + .toList(), + prototypeItem: prototypeItem, + ) + : spacing > 0 + ? ListView.separated( + controller: _controller, + cacheExtent: cacheExtent, + reverse: reverse, + clipBehavior: clipBehavior, + scrollDirection: scrollDirection, + shrinkWrap: shrinkWrap, + padding: padding, + itemCount: widget.children.length, + itemBuilder: (context, index) { + return createControl( + widget.control, ctrls[index].id, disabled, + parentAdaptive: adaptive); + }, + separatorBuilder: (context, index) { + return horizontal + ? dividerThickness == 0 + ? SizedBox(width: spacing) + : VerticalDivider( + width: spacing, thickness: dividerThickness) + : dividerThickness == 0 + ? SizedBox(height: spacing) + : Divider( + height: spacing, thickness: dividerThickness); + }, + ) + : ListView.builder( + controller: _controller, + clipBehavior: clipBehavior, + semanticChildCount: semanticChildCount, + reverse: reverse, + cacheExtent: cacheExtent, + scrollDirection: scrollDirection, + shrinkWrap: shrinkWrap, + padding: padding, + itemCount: widget.children.length, + itemExtent: itemExtent, + itemBuilder: (context, index) { + return createControl( + widget.control, ctrls[index].id, disabled, + parentAdaptive: adaptive); + }, + prototypeItem: prototypeItem, + ); child = ScrollableControl( control: widget.control, diff --git a/sdk/python/packages/flet/src/flet/core/list_tile.py b/sdk/python/packages/flet/src/flet/core/list_tile.py index c0ec8a84a..9e9451c2a 100644 --- a/sdk/python/packages/flet/src/flet/core/list_tile.py +++ b/sdk/python/packages/flet/src/flet/core/list_tile.py @@ -82,15 +82,15 @@ def main(page): def __init__( self, - content_padding: Optional[PaddingValue] = None, - bgcolor: Optional[ColorValue] = None, - bgcolor_activated: Optional[str] = None, - hover_color: Optional[ColorValue] = None, - leading: Optional[Control] = None, title: Optional[Control] = None, subtitle: Optional[Control] = None, - trailing: Optional[Control] = None, is_three_line: Optional[bool] = None, + leading: Optional[Control] = None, + trailing: Optional[Control] = None, + content_padding: PaddingValue = None, + bgcolor: Optional[ColorValue] = None, + bgcolor_activated: Optional[str] = None, + hover_color: Optional[ColorValue] = None, selected: Optional[bool] = None, dense: Optional[bool] = None, autofocus: Optional[bool] = None, @@ -114,8 +114,8 @@ def __init__( subtitle_text_style: Optional[TextStyle] = None, leading_and_trailing_text_style: Optional[TextStyle] = None, min_height: OptionalNumber = None, - on_click=None, - on_long_press=None, + on_click: OptionalControlEventCallable = None, + on_long_press: OptionalControlEventCallable = None, # # ConstrainedControl and AdaptiveControl # diff --git a/sdk/python/packages/flet/src/flet/core/list_view.py b/sdk/python/packages/flet/src/flet/core/list_view.py index 0b9ad1eb1..f74389d26 100644 --- a/sdk/python/packages/flet/src/flet/core/list_view.py +++ b/sdk/python/packages/flet/src/flet/core/list_view.py @@ -1,4 +1,4 @@ -from typing import Any, Callable, List, Optional, Sequence, Union +from typing import Any, List, Optional, Sequence, Union from flet.core.adaptive_control import AdaptiveControl from flet.core.animation import AnimationValue @@ -10,6 +10,7 @@ ClipBehavior, OffsetValue, OptionalControlEventCallable, + OptionalEventCallable, PaddingValue, ResponsiveNumber, RotateValue, @@ -68,13 +69,14 @@ def __init__( clip_behavior: Optional[ClipBehavior] = None, semantic_child_count: Optional[int] = None, cache_extent: OptionalNumber = None, + build_controls_on_demand: Optional[bool] = None, # # ScrollableControl specific # auto_scroll: Optional[bool] = None, reverse: Optional[bool] = None, on_scroll_interval: OptionalNumber = None, - on_scroll: Optional[Callable[[OnScrollEvent], None]] = None, + on_scroll: OptionalEventCallable[OnScrollEvent] = None, # # ConstrainedControl # @@ -160,6 +162,7 @@ def __init__( self.clip_behavior = clip_behavior self.semantic_child_count = semantic_child_count self.cache_extent = cache_extent + self.build_controls_on_demand = build_controls_on_demand def _get_control_name(self): return "listview" @@ -265,3 +268,12 @@ def semantic_child_count(self) -> Optional[int]: @semantic_child_count.setter def semantic_child_count(self, value: Optional[int]): self._set_attr("semanticChildCount", value) + + # build_controls_on_demand + @property + def build_controls_on_demand(self) -> Optional[bool]: + return self._get_attr("buildControlsOnDemand", data_type="bool", def_value=True) + + @build_controls_on_demand.setter + def build_controls_on_demand(self, value: Optional[bool]): + self._set_attr("buildControlsOnDemand", value)