flutter长按列表指定位置弹出菜单

flutter长按列表指定位置弹出菜单

效果如图:
在这里插入图片描述

打算弄个像安卓微信列表长按出菜单的效果
要求:
1.长按列表弹出菜单
2.需要在手势位置弹出
3.想微信哪样若手势位置靠上则向下弹出菜单,若点击位置靠下则向上弹出,若点击位置靠左则向右弹,若点击位置靠右则向左弹。

实现
本来打算直接用 showMenu 弄来着,但position调来调去都没有办法按照预想位置弹出。
后决定通过 showGeneralDialog 手动弄个。
首先要获取点击位置,常用的 InkWell 只有onLongPress,并没有位置信息,所以选用手势更多的GestureDetector(detail){}来获取手势位置信息
获取手势位置信息并调用打开菜单方法代码:

GestureDetector(
    onLongPressStart: (olpdt) async {
    var menuResult = await showRightMenu(context, 
    olpdt.globalPosition.dx,
    olpdt.globalPosition.dy,
    items: [ MapEntry("修改", eventMenuItems.edit),
             MapEntry("删除", eventMenuItems.delete)]);

弹出菜代码实现:

// 按指定位置弹出菜单
//dx,dy:手势位置
//items菜单选项,keey为显示内容,value为返回值
//如果不传items参数可以自定义菜单样式,需要传size和menu
Future showRightMenu(BuildContext context,dx,dy,{List<MapEntry<String,dynamic>> items,Size size,Widget menu}) async{
  
  double sw = MediaQuery.of(context).size.width;//屏幕宽度
  double sh = MediaQuery.of(context).size.height;//屏幕高度
  Border border = dy<sh/2? //
    Border(top:BorderSide(color: Colors.green[200],width: 2)):
    Border(bottom:BorderSide(color: Colors.green[200],width: 2));
//如果传了items参数则根据items生成菜单
  if(items !=null && items.length>0){
    double itemWidth = 100.0;
    double itemHeight = 50.0;
    double menuHeight = itemHeight * items.length+2;
    
    size = Size(itemWidth,menuHeight);

    menu = 
    Container(
      decoration: BoxDecoration(color: Colors.white, border: border),
      child: Column(
      children: items.map<Widget>((e) => InkWell(
        child:Container(
          padding:EdgeInsets.all(10),
          width: itemWidth,
          height: itemHeight,
          child: Text(e.key,style: TextStyle(fontSize: 16),),
        ),
        onTap: (){
          Navigator.pop(context,e.value);
        },
      )).toList(),
  ),
    );

  }
  Size sSize = MediaQuery.of(context).size;
  
// PopupMenuItem

  double menuW = size.width;//菜单宽度
  double menuH = size.height;//菜单高度
  //判断手势位置在屏幕的那个区域以判断最好的弹出方向
  double endL = dx < sw/2?dx:dx-menuW;
  double endT = dy < sh/2?dy:dy-menuH;
  double endR = dx < sw/2?dx+menuW:dx;
  double endB = dy < sh/2?dy+menuH:dy;
  
  return await showGeneralDialog(
    context: context,
    pageBuilder: (context, anim1, anim2) {
	//由于用了组件放大的动画效果,所以用了SingleChildScrollView包裹
	//否则在组件小的时候会出现菜单超出编辑的错误
      return SingleChildScrollView(
        child: menu
      );
    },
    barrierColor: Colors.grey.withOpacity(0),//弹窗后的背景遮罩色,调来调去还是透明的顺眼
    barrierDismissible: true,
    barrierLabel: "",
    transitionDuration: Duration(milliseconds: 200),//动画时间
    
    transitionBuilder: (context, anim1, anim2, child) {
      return Stack(
        children: [
        // 有好多种Transition来实现不同的动画效果,可以参考官方API
          PositionedTransition(
            rect: RelativeRectTween(
              begin: RelativeRect.fromSize(//动画起始位置与元素大小
                  Rect.fromLTWH(dx, dy, 1, 1), sSize),
              end: RelativeRect.fromSize(//动画结束位置与元素大小
                  Rect.fromLTRB(endL,endT,endR,endB),
                  sSize),
            ).animate(CurvedAnimation(parent: anim1, curve: Curves.ease)), 
          child: child)

        ],

      );
    }
    );
}


结束语:
本人是做后台的,flutter纯属爱好,写的有问题的地方还请高手赐教。
真心感觉flutter很棒,希望flutter越来越好!

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 中实现按 item 多选列表可以使用 `ListView`,并在其中添加一个 `LongPressDraggable` 来实现拖拽和选择效果。以下是一个简单的实现示例: ```dart import 'package:flutter/material.dart'; class MultiSelectList extends StatefulWidget { @override _MultiSelectListState createState() => _MultiSelectListState(); } class _MultiSelectListState extends State<MultiSelectList> { List<String> items = [ 'Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7', 'Item 8', 'Item 9', 'Item 10' ]; List<String> selectedItems = []; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Multi Select List'), ), body: ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return LongPressDraggable( data: index, child: ListTile( title: Text(items[index]), subtitle: Text('Long press to select'), selected: selectedItems.contains(items[index]), onLongPress: () { setState(() { if (selectedItems.contains(items[index])) { selectedItems.remove(items[index]); } else { selectedItems.add(items[index]); } }); }, ), feedback: ListTile( title: Text(items[index]), selected: true, ), ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { setState(() { selectedItems.clear(); }); }, child: Icon(Icons.clear), ), ); } } ``` 在这个示例中,我们使用了 `ListView.builder` 来生成一个包含多个 `LongPressDraggable` 的列表。当用户按某个 item 时,我们使用 `setState` 更新 `selectedItems` 列表,并在对应的 `ListTile` 中设置 `selected` 属性以显示选中状态。当用户拖拽某个 item 时,我们使用 `feedback` 属性提供一个反馈的 widget。最后,我们添加了一个清除所有选中项的按钮。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值