flutter 长按弹出菜单,删除,分享,更多,撤回.

flutter聊天界面-聊天气泡长按弹出复制、删除按钮菜单 flutter聊天界面-聊天气泡长按弹出复制、删除按钮菜单,主要实现Canvas结合画笔CustomPainter绘制,根据GestureDetector获取位置,通过findRenderObject、localToGlobal获取当前气泡的大小及位置,最后使用showGeneralDialog弹出。 阅读详情
最近在开发IM软件,需要做:长按弹出菜单,删除,分享,更多,撤回.
先看看效果是不是你想要的



使用处的代码

_menuView() {
    bool isCanRecall = DateTime.now().millisecondsSinceEpoch -
            dateTime.millisecondsSinceEpoch <
        12000;
    var _data = ['复制', '转发', '删除'];
    var menuWidth = 150.0;
    if (isCanRecall && direct == 1) {
      _data.add('撤回');
      menuWidth = 200.0;
    }
    return WPopupMenu(
        menuWidth: menuWidth,
        menuHeight: 30,
        decoration: ShapeDecoration(
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.all(Radius.circular(5))),
        ),
        onValueChanged: (int selected) {
          switch (_data[selected]) {
            case '复制':
              ToastUtils.toast(context, msg: '复制成功');
              Clipboard.setData(ClipboardData(text: text));
              break;
            case '转发':
              _selectMemberPage();
              break;
            case '删除':
              _deleteMsg();
              break;
            case '撤回':
              _recallMsg();
              break;
          }
        },
        pressType: PressType.longPress,
        actions: _data,
        child: _backView(context));
  }
WPopupMenu.dart
import 'package:flutter/material.dart';
import 'package:wechat/common/view/triangle_painter.dart';

const double _kMenuScreenPadding = 8.0;

class WPopupMenu extends StatefulWidget {
  WPopupMenu({
    Key key,
    @required this.onValueChanged,
    @required this.actions,
    @required this.child,
    this.pressType = PressType.longPress,
    this.pageMaxChildCount = 5,
    this.backgroundColor = Colors.black,
    this.menuWidth = 250,
    this.menuHeight = 42,
    this.alignment,
    this.padding,
    Color color,
    Decoration decoration,
    this.foregroundDecoration,
    double width,
    double height,
    BoxConstraints constraints,
    this.margin,
    this.transform,
  })  : assert(onValueChanged != null),
        assert(actions != null && actions.length > 0),
        assert(child != null),
        assert(margin == null || margin.isNonNegative),
        assert(padding == null || padding.isNonNegative),
        assert(decoration == null || decoration.debugAssertIsValid()),
        assert(constraints == null || constraints.debugAssertIsValid()),
        assert(
            color == null || decoration == null,
            'Cannot provide both a color and a decoration\n'
            'The color argument is just a shorthand for "decoration: new BoxDecoration(color: color)".'),
        decoration =
            decoration ?? (color != null ? BoxDecoration(color: color) : null),
        constraints = (width != null || height != null)
            ? constraints?.tighten(width: width, height: height) ??
                BoxConstraints.tightFor(width: width, height: height)
            : constraints,
        super(key: key);

  final BoxConstraints constraints;
  final Decoration decoration;
  final AlignmentGeometry alignment;
  final EdgeInsets padding;
  final Decoration foregroundDecoration;
  final EdgeInsets margin;
  final Matrix4 transform;
  final ValueChanged<int> onValueChanged;
  final List<String> actions;
  final Widget child;
  final PressType pressType; // 点击方式 长按 还是单击
  final int pageMaxChildCount;
  final Color backgroundColor;
  final double menuWidth;
  final double menuHeight;

  @override
  _WPopupMenuState createState() => _WPopupMenuState();
}

class _WPopupMenuState extends State<WPopupMenu> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        key: widget.key,
        padding: widget.padding,
        margin: widget.margin,
        decoration: widget.decoration,
        constraints: widget.constraints,
        transform: widget.transform,
        alignment: widget.alignment,
        child: widget.child,
      ),
      onTap: () {
        if (widget.pressType == PressType.singleClick) {
          onTap();
        }
      },
      onLongPress: () {
        if (widget.pressType == PressType.longPress) {
          onTap();
        }
      },
    );
  }

  void onTap() {
    Navigator.push(
            context,
            _PopupMenuRoute(
                context,
                widget.actions,
                widget.pageMaxChildCount,
                widget.backgroundColor,
                widget.menuWidth,
                widget.menuHeight,
                widget.padding,
                widget.margin))
        .then((index) {
      widget.onValueChanged(index);
    });
  }
}

enum PressType {
  // 长按
  longPress,
  // 单击
  singleClick,
}

class _PopupMenuRoute extends PopupRoute {
  final BuildContext btnContext;
  double _height;
  double _width;
  final List<String> actions;
  final int _pageMaxChildCount;
  final Color backgroundColor;
  final double menuWidth;
  final double menuHeight;
  final EdgeInsets padding;
  final EdgeInsets margin;

  _PopupMenuRoute(
      this.btnContext,
      this.actions,
      this._pageMaxChildCount,
      this.backgroundColor,
      this.menuWidth,
      this.menuHeight,
      this.padding,
      this.margin) {
    _height = btnContext.size.height -
        (padding == null
            ? margin == null ? 0 : margin.vertical
            : padding.vertical);
    _width = btnContext.size.width -
        (padding == null
            ? margin == null ? 0 : margin.horizontal
            : padding.horizontal);
  }

  @override
  Animation<double> createAnimation() {
    return CurvedAnimation(
      parent: super.createAnimation(),
      curve: Curves.linear,
      reverseCurve: const Interval(0.0, 2.0 / 3.0),
    );
  }

  @override
  Color get barrierColor => null;

  @override
  bool get barrierDismissible => true;

  @override
  String get barrierLabel => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    return _MenuPopWidget(
        this.btnContext,
        _height,
        _width,
        actions,
        _pageMaxChildCount,
        backgroundColor,
        menuWidth,
        menuHeight,
        padding,
        margin);
  }

  @override
  Duration get transitionDuration => Duration(milliseconds: 300);
}

class _MenuPopWidget extends StatefulWidget {
  final BuildContext btnContext;
  final double _height;
  final double _width;
  final List<String> actions;
  final int _pageMaxChildCount;
  final Color backgroundColor;
  final double menuWidth;
  final double menuHeight;
  final EdgeInsets padding;
  final EdgeInsets margin;

  _MenuPopWidget(
    this.btnContext,
    this._height,
    this._width,
    this.actions,
    this._pageMaxChildCount,
    this.backgroundColor,
    this.menuWidth,
    this.menuHeight,
    this.padding,
    this.margin,
  );

  @override
  __MenuPopWidgetState createState() => __MenuPopWidgetState();
}

class __MenuPopWidgetState extends State<_MenuPopWidget> {
  int _curPage = 0;
  final double _arrowWidth = 40;
  final double _separatorWidth = 1;
  final double _triangleHeight = 10;

  RenderBox button;
  RenderBox overlay;
  RelativeRect position;

  @override
  void initState() {
    super.initState();
    button = widget.btnContext.findRenderObject();
    overlay = Overlay.of(widget.btnContext).context.findRenderObject();
    position = RelativeRect.fromRect(
      Rect.fromPoints(
        button.localToGlobal(
            Offset(
                widget.padding == null
                    ? widget.margin == null ? 0 : widget.margin.left
                    : widget.padding.left,
                widget.padding == null
                    ? widget.margin == null ? 0 : widget.margin.top
                    : widget.padding.top),
            ancestor: overlay),
        button.localToGlobal(
            Offset(
                widget.padding == null
                    ? widget.margin == null ? 0 : widget.margin.left
                    : widget.padding.left,
                widget.padding == null
                    ? widget.margin == null ? 0 : widget.margin.top
                    : widget.padding.top),
            ancestor: overlay),
      ),
      Offset.zero & overlay.size,
    );
  }

  @override
  Widget build(BuildContext context) {
    // 这里计算出来 当前页的 child 一共有多少个
    int _curPageChildCount =
        (_curPage + 1) * widget._pageMaxChildCount > widget.actions.length
            ? widget.actions.length % widget._pageMaxChildCount
            : widget._pageMaxChildCount;

    double _curArrowWidth = 0;
    int _curArrowCount = 0; // 一共几个箭头

    if (widget.actions.length > widget._pageMaxChildCount) {
      // 数据长度大于 widget._pageMaxChildCount
      if (_curPage == 0) {
        // 如果是第一页
        _curArrowWidth = _arrowWidth;
        _curArrowCount = 1;
      } else {
        // 如果不是第一页 则需要也显示左箭头
        _curArrowWidth = _arrowWidth * 2;
        _curArrowCount = 2;
      }
    }

    double _curPageWidth = widget.menuWidth +
        (_curPageChildCount - 1 + _curArrowCount) * _separatorWidth +
        _curArrowWidth;

    return MediaQuery.removePadding(
      context: context,
      removeTop: true,
      removeBottom: true,
      removeLeft: true,
      removeRight: true,
      child: Builder(
        builder: (BuildContext context) {
          var isInverted = (position.top +
                  (MediaQuery.of(context).size.height -
                          position.top -
                          position.bottom) /
                      2.0 -
                  (widget.menuHeight + _triangleHeight)) <
              (widget.menuHeight + _triangleHeight) * 2;
          return CustomSingleChildLayout(
            // 这里计算偏移量
            delegate: _PopupMenuRouteLayout(
                position,
                widget.menuHeight + _triangleHeight,
                Directionality.of(widget.btnContext),
                widget._width,
                widget.menuWidth,
                widget._height),
            child: SizedBox(
              height: widget.menuHeight + _triangleHeight,
              width: _curPageWidth,
              child: Material(
                color: Colors.transparent,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    isInverted
                        ? CustomPaint(
                            size: Size(_curPageWidth, _triangleHeight),
                            painter: TrianglePainter(
                              color: widget.backgroundColor,
                              position: position,
                              isInverted: true,
                              size: button.size,
                              screenWidth: MediaQuery.of(context).size.width,
                            ),
                          )
                        : Container(),
                    Expanded(
                      child: Stack(
                        children: <Widget>[
                          ClipRRect(
                            borderRadius: BorderRadius.all(Radius.circular(5)),
                            child: Container(
                              color: widget.backgroundColor,
                              height: widget.menuHeight,
                            ),
                          ),
                          Row(
                            mainAxisSize: MainAxisSize.min,
                            children: <Widget>[
                              // 左箭头:判断是否是第一页,如果是第一页则不显示
                              _curPage == 0
                                  ? Container(
                                      height: widget.menuHeight,
                                    )
                                  : InkWell(
                                      onTap: () {
                                        setState(() {
                                          _curPage--;
                                        });
                                      },
                                      child: Container(
                                        width: _arrowWidth,
                                        height: widget.menuHeight,
                                        child: Image.asset(
                                          'images/left_white.png',
                                          fit: BoxFit.none,
                                        ),
                                      ),
                                    ),
                              // 左箭头:判断是否是第一页,如果是第一页则不显示
                              _curPage == 0
                                  ? Container(
                                      height: widget.menuHeight,
                                    )
                                  : Container(
                                      width: 1,
                                      height: widget.menuHeight,
                                      color: Colors.grey,
                                    ),

                              // 中间是ListView
                              _buildList(_curPageChildCount, _curPageWidth,
                                  _curArrowWidth, _curArrowCount),

                              // 右箭头:判断是否有箭头,如果有就显示,没有就不显示
                              _curArrowCount > 0
                                  ? Container(
                                      width: 1,
                                      color: Colors.grey,
                                      height: widget.menuHeight,
                                    )
                                  : Container(
                                      height: widget.menuHeight,
                                    ),
                              _curArrowCount > 0
                                  ? InkWell(
                                      onTap: () {
                                        if ((_curPage + 1) *
                                                widget._pageMaxChildCount <
                                            widget.actions.length)
                                          setState(() {
                                            _curPage++;
                                          });
                                      },
                                      child: Container(
                                        width: _arrowWidth,
                                        height: widget.menuHeight,
                                        child: Image.asset(
                                          (_curPage + 1) *
                                                      widget
                                                          ._pageMaxChildCount >=
                                                  widget.actions.length
                                              ? 'images/right_gray.png'
                                              : 'images/right_white.png',
                                          fit: BoxFit.none,
                                        ),
                                      ),
                                    )
                                  : Container(
                                      height: widget.menuHeight,
                                    ),
                            ],
                          ),
                        ],
                      ),
                    ),
                    isInverted
                        ? Container()
                        : CustomPaint(
                            size: Size(_curPageWidth, _triangleHeight),
                            painter: TrianglePainter(
                                color: widget.backgroundColor,
                                position: position,
                                size: button.size,
                              screenWidth: MediaQuery.of(context).size.width,),
                          ),
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }

  Widget _buildList(int _curPageChildCount, double _curPageWidth,
      double _curArrowWidth, int _curArrowCount) {
    return ListView.separated(
      shrinkWrap: true,
      physics: NeverScrollableScrollPhysics(),
      scrollDirection: Axis.horizontal,
      itemCount: _curPageChildCount,
      itemBuilder: (BuildContext context, int index) {
        return InkWell(
          onTap: () {
            Navigator.pop(
                context, _curPage * widget._pageMaxChildCount + index);
          },
          child: SizedBox(
            width: (_curPageWidth -
                    _curArrowWidth -
                    (_curPageChildCount - 1 + _curArrowCount) *
                        _separatorWidth) /
                _curPageChildCount,
            height: widget.menuHeight,
            child: Center(
              child: Text(
                widget.actions[_curPage * widget._pageMaxChildCount + index],
                style: TextStyle(color: Colors.white, fontSize: 12),
              ),
            ),
          ),
        );
      },
      separatorBuilder: (BuildContext context, int index) {
        return Container(
          width: 1,
          height: widget.menuHeight,
          color: Colors.grey,
        );
      },
    );
  }
}

// Positioning of the menu on the screen.
class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
  _PopupMenuRouteLayout(this.position, this.selectedItemOffset,
      this.textDirection, this.width, this.menuWidth, this.height);

  // Rectangle of underlying button, relative to the overlay's dimensions.
  final RelativeRect position;

  // The distance from the top of the menu to the middle of selected item.
  //
  // This will be null if there's no item to position in this way.
  final double selectedItemOffset;

  // Whether to prefer going to the left or to the right.
  final TextDirection textDirection;

  final double width;
  final double height;
  final double menuWidth;

  // We put the child wherever position specifies, so long as it will fit within
  // the specified parent size padded (inset) by 8. If necessary, we adjust the
  // child's position so that it fits.

  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    // The menu can be at most the size of the overlay minus 8.0 pixels in each
    // direction.
    return BoxConstraints.loose(constraints.biggest -
        const Offset(_kMenuScreenPadding * 2.0, _kMenuScreenPadding * 2.0));
  }

  @override
  Offset getPositionForChild(Size size, Size childSize) {
    // size: The size of the overlay.
    // childSize: The size of the menu, when fully open, as determined by
    // getConstraintsForChild.

    // Find the ideal vertical position.
    double y;
    if (selectedItemOffset == null) {
      y = position.top;
    } else {
      y = position.top +
          (size.height - position.top - position.bottom) / 2.0 -
          selectedItemOffset;
    }

    // Find the ideal horizontal position.
    double x;

    // 如果menu 的宽度 小于 child 的宽度,则直接把menu 放在 child 中间
    if (childSize.width < width) {
      x = position.left + (width - childSize.width) / 2;
    } else {
      // 如果靠右
      if (position.left > size.width - (position.left + width)) {
        if (size.width - (position.left + width) > childSize.width / 2 + _kMenuScreenPadding) {
          x = position.left - (childSize.width - width) / 2;
        } else
          x = position.left + width - childSize.width;
      } else if (position.left < size.width - (position.left + width)) {
        if (position.left > childSize.width / 2 + _kMenuScreenPadding) {
          x = position.left - (childSize.width - width) / 2;
        } else
          x = position.left;
      } else {
        x = position.right - width / 2 - childSize.width / 2;
      }
    }

    if (y < _kMenuScreenPadding)
      y = _kMenuScreenPadding;
    else if (y + childSize.height > size.height - _kMenuScreenPadding)
      y = size.height - childSize.height;
    else if (y < childSize.height * 2) {
      y = position.top + height;
    }
    return Offset(x, y);
  }

  @override
  bool shouldRelayout(_PopupMenuRouteLayout oldDelegate) {
    return position != oldDelegate.position;
  }
}


再次感谢原文作者,在原文作者上进行的修改
https:// juejin.im/post/5d51f543e51d4561ff6667ee

更多详解:
喜欢可以加Q群号:913934649,点赞,评论;

简书: https://www.jianshu.com/u/88db5f15770d

csdn:https://me.youkuaiyun.com/beyondforme

掘金:https://juejin.im/user/5e09a9e86fb9a016271294a7

flutter长按列表指定位置弹出菜单 flutter长按列表指定位置弹出菜单 效果如图: 打算弄个像安卓微信列表长按出菜单的效果 要求: 1.长按列表弹出菜单 2.需要在手势位置弹出 3.想微信哪样若手势位置靠上则向下弹出菜单,若点击位置靠下则向上弹出,若点击位置靠左则向右弹,若点击位置靠右则向左弹。 。 实现 本来打算直接用 showMenu 弄来着,但position调来调去都没有办法按照预想位置弹出。 后决定通过 showGeneralDialog 手动弄个。 首先要获取点击位置,常用的 InkWell 只有onLongPress,并没 阅读详情

相关推荐

flutter开发实战-自定义长按TextField输入框剪切、复制、选择全部菜单AdaptiveTextSelectionToolba样式UI效果

flutter开发实战-自定义长按TextField输入框剪切、复制、选择全部菜单样式UI效果。自定义AdaptiveTextSelectionToolbar,在TextField输入框中设置contextMenuBuilder,实现功能。

一名开发者 4490

Flutter 长按表示弹出菜单后点击菜单跳转画面

Flutter 长按表示弹出菜单后点击菜单跳转画面

m0_59162559的博客 1750

Flutter开发专家指南:如何优雅地实现弹出菜单

你可以通过自定义MenuItem的样式和行为来进一步定制弹出菜单。例如,你可以改变文本的颜色、添加图标、或者改变菜单的布局。MenuItem(Text('选项1', style: TextStyle(color: Colors.blue)),],),print('选项1被点击');},),// 其他菜单项...],),在这个例子中,我们为MenuItem添加了一个Icon和一个自定义颜色的文本。

理论都是虚的,代码才是王道。 509

Flutter:功能型组件(2)- 弹出菜单、弹出提示

Flutter:功能型组件(2)- 弹出菜单、弹出提示

weixin_41897680的博客 4195

导数在工程与AI中的12个实战应用解析

导数作为数学中的基本概念,本质是描述变化率的工具,其核心价值在于将非线性问题局部线性化处理。从原理上看,通过极限过程捕捉函数瞬时变化特性,使工程师能精确控制系统动态行为,帮助科学家量化自然规律变化速率。在技术实现层面,现代符号计算(如Mathematica)、数值计算(如MATLAB)和自动微分(如PyTorch)工具链的发展,大幅提升了导数计算的效率与精度。典型应用场景涵盖机械控制(如ABS防抱死系统)、金融工程(如期权希腊值计算)、医疗影像(如Canny边缘检测)等领域。特别在机器学习中,反向传播算法依

weixin_35509395的博客 316

Hermes Dashboard Web 端部署完整说明

通过反向代理(nginx)使用公网域名访问时,会遇到 Host 头校验、CORS 跨域、WebSocket 连接拒绝三个核心问题。本文档记录了完整的源码修改方案和部署步骤。确保 nginx 主配置加载了 WebSocket map(宝塔默认为。路径的公开访问(无需登录),其他路径仍受 Cookie 认证保护。Hermes Dashboard 默认绑定。访问站点时会先弹出浏览器密码框,输入用户。在 nginx 反向代理配置中的。环境变量动态读取允许的域名。nginx 配置中已添加。

大白菜代码的博客 804

Flutter PopupMenu 仿微信聊天长按弹出菜单,删除,分享,更多,撤回

最近在开发IM软件,需要做:长按弹出菜单,删除,分享,更多,撤回. 先看看效果是不是你想要的 使用处的代码 _menuView() { bool isCanRecall = DateTime.now().millisecondsSinceEpoch - dateTime.millisecondsSinceEpoch < 12000; ...

仰望星空 2950

西门子S7-1200与S7-200SMART的PROFINET通讯实战:从GSD文件生成到数据监控

本文详细解析了西门子S7-1200与S7-200SMART之间实现PROFINET通讯的完整实战流程。核心内容包括将S7-200SMART配置为智能IO设备、生成并安装GSD文件、在TIA Portal中进行网络组态与地址映射,最终实现双向数据交换与监控。该方案为整合新旧设备、构建灵活高效的工业自动化系统提供了可靠路径。

weixin_29271263的博客 245

短视频app制作开发flutter 长按弹出菜单,删除,分享,更多,撤回.

使用处的代码 _menuView() { bool isCanRecall = DateTime.now().millisecondsSinceEpoch - dateTime.millisecondsSinceEpoch < 12000; var _data = ['复制', '转发', '删除']; var menuWidth = 150.0; if (isCanRecall && direct == 1) {

云豹网络科技 4058

VSCode终端打不开?3分钟搞定Windows下Terminal配置(附最新JSON设置方法)

本文针对Windows系统下VSCode终端无法启动的常见问题,提供了详细的诊断与解决方案。核心在于更新已弃用的旧配置,采用最新的JSON设置方法,通过定义`terminal.integrated.profiles.windows`和指定`terminal.integrated.defaultProfile.windows`,快速修复并优化终端配置,实现三分钟内恢复正常使用。

flower的专栏 741

利用 Python 构建高效爬虫爬取国家标准文献——从基础到进阶

然而,由于许多标准文献需要从特定网站获取,手动下载既耗时又低效,因此构建自动化爬虫成为一种实用且高效的解决方案。本文从技术选型、网站分析、代码实现到反爬优化,全面讲解了如何爬取国家标准文献。国家标准文献(National Standards Literature)是国家对各领域统一规范的文件,涵盖了技术参数、测试方法、生产工艺等内容。因此,通过自动化爬虫技术进行文献爬取和管理,不仅能解放劳动力,还可以提高数据管理效率。在构建爬虫前,我们需要对目标网站进行分析,包括页面结构、请求方式以及可能的反爬机制。

2201_76125261的博客 2104

flutter 点击位置弹出菜单栏(仿微信文本长按位置下方弹出菜单)

效果图: 添加链接描述

qq_36071410的博客 7279

LabVIEW实现TCP通信

在本节中,我们将简要探讨TCP通信的基础知识,并以工业物联网平台TLINK中的云端设备数据发布设计为例,详细阐述在互联网环境下TCP客户端应用程序设计的基本方法。

不脱发的程序猿 1960

Flutter 10天高仿大厂App及小技巧积累总结,被阿里面试官征服了

} } 调用非常简单,可自定义颜色、字体大小;GStyle.iconfont(0xe635, color: Colors.orange, size: 17.0) 5、flutter实现badge红点/圆点提示 ======================= ![](https://imgconvert.csdnimg.cn/aHR0cDovL3BiMy5wc3RhdHAuY29tL2xhcmdlL 3BnYy1pbWFnZS8zZTMxNDBjMWNmODU0ZGM0ODQ3ZjAwZTU2NWVkNzI1

m0_66264324的博客 775

基于YOLOv8深度学习的火焰与烟雾检测系统详解:UI界面 + YOLOv8 + 数据集的实现

通过自动化检测火焰和烟雾,可以提高响应速度,减少潜在的火灾损失,保障人身和财产安全。此外,应用还会显示标记了检测框的视频画面,方便用户直观了解检测效果。同时,前端界面将使用Streamlit来实现,因其可以快速搭建交互式应用,适合我们的需求。要训练一个有效的火焰和烟雾检测模型,我们需要一个包含火焰和烟雾图片的数据集。为了保证模型的准确性和泛化能力,建议收集至少500张火焰和烟雾的图片,保证数据的多样性和代表性。训练过程中,模型会输出每个Epoch的训练损失和验证准确率,便于我们监控模型的学习情况。

YOLO 1321

秋招突击——笔试整理——8/25——拼多多笔试整理

继续加油! 转变思维,有简单到复杂,由直观到抽象,这种贪心模拟的题目一直是这样的!

Blackoutdragon的博客 2400

Flutter | TextField长按时选项菜单复制、粘贴显示为英文问题解决

长按TextField后,显示剪切、复制等选项为英文,如下图所示,这是因为问未设置语言本地化,我们需要进行设置。

^_^ 2483

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

flutter 仿微信长按弹窗复制撤回粘贴收藏等自定义定制

根据https://blog.csdn.net/qq_23756803/article/details/99519441 这里的代码实现了功能,但是很多地方依然有问题,需要配置图片,还需要处理样式的箭头,以及多行的bug 所以我自己修改了很多地方的代码,封装了一个 import 'package:flutter/material.dart'; import 'package:lvsongguo/utils/widget_w_popup/triangle_painter.dart'; c...

whs867712232的博客 2150

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Flutter 弹出菜单实现(不是显示的菜单按钮,隐式的)showMenu

隐式的菜单效果图代码实现 没有完全的理解,但是怎么说呢,好歹算是实现了。???? 效果图 简单在页面中有一个图片,长按图片的时候呢就会触发菜单的显示。 效果图 代码实现 一个带有长按功能的按钮 GestureDetector( //手势包含添加按钮 实现点击进行选择图片 child:Image.asset('images/addphoto.png'), onLongPressStart: (LongPressStar

qigaidawang111的博客 5852

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Flutter之简单实现购物车功能代码+逻辑

一、初始化时判断是否为登录状态,假设是登录状态从本地中取出token,带参传递给后端请求登录后购物车数据 二、分析点击全选和非全选状态 1.全选状态就是把数组中的数据对应的每个check值设置为true,总价就是后端返回的全选数量的总价格 设置全选和非全选 这个的改变是由初始化查询数组列表中是否为全选或非全选状态所决定,如果遇见一个check为false那么就返回false 2.非全选状态(总价结果为0或者当前选中对象的总价之和) 判断是否非全选状态 三、改变单个物品check,触发checkCa

可可的博客 3016

Flutter Chip的使用

Chip 属性介绍avatar左侧图标组件label@required 文本 WidgetlabelStyle文本样式,TextStyle文本外边距 PaddingdeleteIcon右侧删除按钮 WidgetonDeleted删除按钮点击事件删除按钮颜色长按删除按钮的提示语shape形状,ShapeBorder裁剪方式,默认为 Clip.nonefocusNode焦点控制,Flutter 组件之 FocusNode 详解autofocus。...

Dream It Possible 2006

flutter TextFiled长按禁止弹出键盘,点击弹出键盘

时,虽然会触发长按事件,但不会显示键盘。

Z20210224的博客 821

Flutter 如何实现显示上下文自定义菜单

Flutter 实现长按显示上下文自定义菜单 很多场景需要我们点击或长按显示操作菜单,如点击gridview中的一项显示上下文菜单,本博就以gridview来作为例子,具体效果如下 要在指定的位置显示上下文菜单,需要解决以下几个问题 淡化当前页面,如同我们显示对话框淡化背景一样 定位上下文菜单显示位置 点击淡化的背景,关闭上下文菜单,回复之前的状态 让我们来按顺序解决这几个问题,首先我们来解...

zhuangch的专栏 2362

Flutter Focused Menu 使用教程

Flutter Focused Menu 使用教程 1. 项目介绍 focused_menu 是一个为 Flutter 应用程序添加聚焦长按菜单的简单易用包。它允许开发者通过包装现有的小部件,快速实现一个交互式的菜单,当用户长按某个元素时,菜单会显示出来。 2. 项目快速启动 首先,您需要在您的 Flutter 项目中添加依赖项。 在 pubspec.yaml 文件中,加入以下代码: depend...

gitblog_00129的博客 445
上一篇: Flutter PopupMenu 仿微信聊天长按弹出菜单,删除,分享,更多,撤回
下一篇: flutter 长按弹出菜单,删除,分享,更多,撤回.
张漂亮2号
博客等级 码龄12年 73粉丝 209原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值