SelectionMenu class

author:郑再红 email:1096877329@qq.com date: 2024-02-01 time: 14:58 describe: 下拉选择菜单组件 - 高度可定制的下拉框解决方案 Enterprise-level dropdown selection menu component - Highly customizable dropdown solution

功能特性 / Features: • 完全自定义 - 按钮和下拉内容完全由开发者控制 • 智能定位 - 自动检测屏幕边界,防止溢出 • 丰富动画 - 支持自定义过渡动画效果 • 🖱多种触发 - 支持点击、悬停等多种交互方式 • 灵活尺寸 - 支持固定宽度或自适应父组件宽度 • 精确对齐 - 支持左对齐、右对齐、居中对齐 • 状态管理 - 提供Controller进行外部控制 • Material风格 - 支持阴影、圆角、颜色等Material属性

使用示例 / Usage Examples:

// 示例1: 基础下拉菜单
// Example 1: Basic dropdown menu
SelectionMenu(
  popWidth: 200,
  buttonBuilder: (show) {
    return Container(
      height: 40,
      width: 200,
      alignment: Alignment.center,
      padding: const EdgeInsets.only(left: 10, right: 10),
      decoration: BoxDecoration(
        color: Colors.grey.withOpacity(0.2),
        borderRadius: BorderRadius.circular(10),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text("请选择"),
          Icon(show ? Icons.arrow_drop_up : Icons.arrow_drop_down),
        ],
      ),
    );
  },
  selectorBuilder: (context) {
    return Container(
      height: 200,
      margin: const EdgeInsets.only(top: 3),
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(5),
        boxShadow: [
          BoxShadow(
            color: Colors.black12,
            blurRadius: 8,
            offset: Offset(0, 2),
          ),
        ],
      ),
      child: ListView.separated(
        itemCount: 20,
        itemBuilder: (context, index) {
          return GestureDetector(
            onTap: () {
              // 处理选择逻辑
              print("选择了: item $index");
            },
            child: Padding(
              padding: const EdgeInsets.symmetric(vertical: 8),
              child: Text(
                "item $index",
                style: TextStyle(fontSize: 16, color: Colors.black),
              ),
            ),
          );
        },
        separatorBuilder: (BuildContext context, int index) {
          return const Divider();
        },
      ),
    );
  },
)

// 示例2: 使用Controller控制下拉菜单
// Example 2: Using controller to control dropdown
final controller = SelectionMenuController();

SelectionMenu(
  controller: controller,
  popWidth: 200,
  buttonBuilder: (show) => Text("点击展开"),
  selectorBuilder: (context) {
    return Container(
      child: ElevatedButton(
        onPressed: () {
          controller.closePop(); // 关闭下拉菜单
        },
        child: Text("关闭"),
      ),
    );
  },
)

// 示例3: 鼠标悬停触发
// Example 3: Hover trigger
SelectionMenu(
  enableOnHover: true,
  enableClick: false,
  popWidth: 150,
  buttonBuilder: (show) => Text("悬停显示"),
  selectorBuilder: (context) => Container(
    height: 100,
    child: Text("悬停内容"),
  ),
)

// 示例4: 右对齐下拉菜单
// Example 4: Right-aligned dropdown
SelectionMenu(
  alignType: AlignType.right,
  popWidth: 200,
  buttonBuilder: (show) => Text("右对齐"),
  selectorBuilder: (context) => Container(
    height: 150,
    child: Text("下拉内容"),
  ),
)

// 示例5: 自定义Material样式
// Example 5: Custom Material style
SelectionMenu(
  popWidth: 200,
  elevation: 8.0,
  color: Colors.white,
  materialBorderRadius: BorderRadius.circular(12),
  shadowColor: Colors.blue.withOpacity(0.3),
  buttonBuilder: (show) => Text("自定义样式"),
  selectorBuilder: (context) => Container(
    height: 200,
    child: Text("内容"),
  ),
)

⚠️ 注意事项 / Notes: • SelectionMenu不管理数据状态,需要外部自行管理选中状态 • 下拉内容会自动检测屏幕边界,避免溢出 • 使用Controller可以实现外部控制打开/关闭 • buttonBuilder的show参数表示当前下拉菜单是否展开 • 建议在selectorBuilder中处理选择逻辑并更新UI • 支持自定义位置布局,使用layoutSelectPop参数

Inheritance
Available extensions

Constructors

SelectionMenu({required WidgetBuilder selectorBuilder, required DropDownButtonBuilder? buttonBuilder, SelectionMenuController? controller, LayoutSelectPop? layoutSelectPop, DropDownPopCreated? onCreated, DropDownPopShow? onShow, DropDownPopDismiss? onDismiss, bool enableOnHover = false, bool enableClick = true, bool matchParentWidth = true, double popWidth = 0, double hMargin = 0, double vMargin = 0, double popHeight = 200, BorderRadiusGeometry? materialBorderRadius, Color? color = Colors.transparent, ShapeBorder? shape, double elevation = 0.0, Color? shadowColor, String? barrierLabel, Color? barrierColor, bool barrierDismissible = true, Duration transitionDuration = const Duration(milliseconds: 200), AlignType alignType = AlignType.left, GestureTapCallback? onDoubleTap, GestureLongPressCallback? onLongPress, GestureTapDownCallback? onTapDown, GestureTapUpCallback? onTapUp, GestureTapCancelCallback? onTapCancel, ValueChanged<bool>? onHighlightChanged, ValueChanged<bool>? onHover, MouseCursor? mouseCursor, Color? focusColor, Color? hoverColor, Color? highlightColor, WidgetStateProperty<Color?>? overlayColor, Color? splashColor, InteractiveInkFeatureFactory? splashFactory, double? radius, BorderRadius? borderRadius, ShapeBorder? customBorder, bool enableFeedback = true, bool excludeFromSemantics = false, FocusNode? focusNode, bool canRequestFocus = true, ValueChanged<bool>? onFocusChange, bool autofocus = false, Key? key})
const

Properties

alignType → AlignType
对齐方式
final
autofocus → bool
final
barrierColor → Color?
final
barrierDismissible → bool
是否允许点击其他区域消失
final
barrierLabel → String?
final
borderRadius → BorderRadius?
final
buttonBuilder → DropDownButtonBuilder?
下拉框构建器
final
canRequestFocus → bool
final
color → Color?
final
controller → SelectionMenuController?
final
customBorder → ShapeBorder?
final
elevation → double
阴影
final
enableClick → bool
是否开启点击
final
enableFeedback → bool
final
enableOnHover → bool
是否开启鼠标悬浮
final
excludeFromSemantics → bool
final
focusColor → Color?
final
focusNode → FocusNode?
final
hashCode → int
The hash code for this object.
no setterinherited
highlightColor → Color?
final
hMargin → double
水平边距
final
hoverColor → Color?
final
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
layoutSelectPop → LayoutSelectPop?
自定义下拉框位置
final
matchParentWidth → bool
当设置的宽度小于 父组件宽度时, 是否匹配父组件宽度,默认true
final
materialBorderRadius → BorderRadiusGeometry?
Material 背景样式
final
mouseCursor → MouseCursor?
final
onCreated → DropDownPopCreated?
下拉框创建
final
onDismiss → DropDownPopCreated?
下拉框消失
final
onDoubleTap → GestureTapCallback?
final
onFocusChange → DropDownPopCreated?
final
onHighlightChanged → DropDownPopCreated?
final
onHover → DropDownPopCreated?
final
onLongPress → GestureTapCallback?
final
onShow → DropDownPopCreated?
下拉框显示
final
onTapCancel → GestureTapCallback?
final
onTapDown → GestureTapDownCallback?
final
onTapUp → GestureTapUpCallback?
final
overlayColor → WidgetStateProperty<Color?>?
final
popHeight → double
窗口高度
final
popWidth → double
下拉框宽度 弹窗部分
final
radius → double?
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
selectorBuilder → WidgetBuilder
下拉框样式构件 弹出部分
final
shadowColor → Color?
阴影颜色
final
shape → ShapeBorder?
final
splashColor → Color?
final
splashFactory → InteractiveInkFeatureFactory?
final
transitionDuration → Duration
动画时间
final
vMargin → double
垂直 边距
final

Methods

blurred({double blur = 5, Color blurColor = Colors.white, BorderRadius? borderRadius, double colorOpacity = 0.5, Widget? overlay, AlignmentGeometry alignment = Alignment.center}) → Blur

Available on Widget, provided by the BlurExtension extension

createElement() → StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() → State<SelectionMenu>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
frosted({double blur = 5, Color frostColor = Colors.white, AlignmentGeometry alignment = Alignment.center, double? height, double? width, double frostOpacity = 0.0, BorderRadius? borderRadius, EdgeInsetsGeometry padding = EdgeInsets.zero}) → Blur

Available on Widget, provided by the FrostExtension extension

noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
Returns a one-line detailed description of the object.
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited