Skip to content

馃悰 Combobox with only one item raises error when clicked#1346

Description

@albertoaliberti

Describe the bug
When a ComboBox contains only one item, opening it throws an exception:

Invalid argument(s): 0.0

When the exception was thrown, this was the stack:
#0      double.clamp (dart:core-patch/double.dart:225:7)
#1      _ComboBoxResizeClipper.getClip (package:fluent_ui/src/controls/form/combo_box.dart:400:33)
#2      _RenderCustomClip._updateClip (package:flutter/src/rendering/proxy_box.dart:1556:25)
#3      RenderClipRRect.hitTest (package:flutter/src/rendering/proxy_box.dart:1735:7)
#4      RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#5      RenderCustomPaint.hitTestChildren (package:flutter/src/rendering/custom_paint.dart:564:18)
#6      RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#7      RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#8      RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#9      RenderShiftedBox.hitTestChildren.<anonymous closure> (package:flutter/src/rendering/shifted_box.dart:112:24)
#10     BoxHitTestResult.addWithPaintOffset (package:flutter/src/rendering/box.dart:841:31)
#11     RenderShiftedBox.hitTestChildren (package:flutter/src/rendering/shifted_box.dart:107:21)
#12     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#13     _RenderLayoutBuilder.hitTestChildren (package:flutter/src/widgets/layout_builder.dart:464:19)
#14     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#15     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#16     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#17     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#18     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#19     RenderIgnorePointer.hitTest (package:flutter/src/rendering/proxy_box.dart:3798:31)
#20     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#21     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#22     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#23     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#24     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#25     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#26     RenderOffstage.hitTest (package:flutter/src/rendering/proxy_box.dart:3929:31)
#27     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#28     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#29     _RenderTheaterMixin.hitTestChildren.childHitTest (package:flutter/src/widgets/overlay.dart:1145:22)
#30     BoxHitTestResult.addWithPaintOffset (package:flutter/src/rendering/box.dart:841:31)
#31     _RenderTheaterMixin.hitTestChildren (package:flutter/src/widgets/overlay.dart:1146:22)
#32     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#33     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#34     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#35     RenderAbsorbPointer.hitTest (package:flutter/src/rendering/proxy_box.dart:4050:56)
#36     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#37     RenderProxyBoxWithHitTestBehavior.hitTest (package:flutter/src/rendering/proxy_box.dart:186:19)
#38     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#39     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#40     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#41     RenderCustomPaint.hitTestChildren (package:flutter/src/rendering/custom_paint.dart:564:18)
#42     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#43     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#44     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#45     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#46     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#47     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#48     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#49     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#50     RenderTapRegionSurface.hitTest (package:flutter/src/widgets/tap_region.dart:234:28)
#51     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#52     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#53     RenderProxyBoxMixin.hitTestChildren (package:flutter/src/rendering/proxy_box.dart:131:19)
#54     RenderBox.hitTest (package:flutter/src/rendering/box.dart:2953:11)
#55     RenderView.hitTest (package:flutter/src/rendering/view.dart:309:12)
#56     RendererBinding.hitTestInView (package:flutter/src/rendering/binding.dart:676:34)
#57     RendererBinding.initMouseTracker.<anonymous closure> (package:flutter/src/rendering/binding.dart:459:11)
#58     MouseTracker._findAnnotations (package:flutter/src/rendering/mouse_tracker.dart:255:60)
#59     MouseTracker.updateAllDevices.<anonymous closure> (package:flutter/src/rendering/mouse_tracker.dart:370:70)
#60     MouseTracker._deviceUpdatePhase (package:flutter/src/rendering/mouse_tracker.dart:204:9)
#61     MouseTracker.updateAllDevices (package:flutter/src/rendering/mouse_tracker.dart:367:5)
#62     RendererBinding._scheduleMouseTrackerUpdate.<anonymous closure> (package:flutter/src/rendering/binding.dart:526:22)
#63     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1430:15)
#64     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1357:11)
#65     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1198:5)
#66     _invoke (dart:ui/hooks.dart:423:13)
#67     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:447:5)
#68     _drawFrame (dart:ui/hooks.dart:395:31)

This worked correctly in previous versions of fluent_ui.

To Reproduce

Minimal example:

import 'package:fluent_ui/fluent_ui.dart';

class ComboboxDemo extends StatefulWidget {
  const ComboboxDemo({super.key});

  @override
  State<ComboboxDemo> createState() => _ComboboxStateDemo();
}

class _ComboboxStateDemo extends State<ComboboxDemo> {
  final _items = ["something"];
  String? _selected = "something";

  @override
  Widget build(BuildContext context) {
    return ComboBox<String>(
      items: _items
          .map((i) => ComboBoxItem(value: i, child: Text(i)))
          .toList(),
      value: _selected,
      onChanged: (value) => setState(() => _selected = value),
    );
  }
}

Steps:

Create a ComboBox with exactly one item.
Click the ComboBox to open the dropdown.
The exception is thrown.

Environment

Flutter: 3.44.8
Dart: 3.12.2
fluent_ui: 4.16.0

Expected behavior
Opening a ComboBox with a single item should not throw an exception.

Additional context
The exception seems to come from a double.clamp() call where the lower bound becomes greater than the upper bound during the flyout positioning calculation.

Metadata

Metadata

Labels

bugSomething isn't workingw: ComboBoxRelated to the ComboBox widget.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions