乐趣区

关于ios:Flutter仿微信的下拉弹框

在挪动开发中,下拉弹框是一种很常见的抉择交互方式,成果如下图所示。

对于这种弹框,咱们能够应用 Dialog 来实现,上面是自定义弹框的次要代码。

Color _bgColor = Colors.white;
double cellHeight = 34;
double cellWidth=120;

typedef ClickCallBack = void Function(int selectIndex, String selectText);

class PopMenus {
  static void showPop(
      {@required BuildContext context,
      @required List<String> listData,
      @required String selText,
      ClickCallBack clickCallback}) {Widget _buildMenuLineCell(dataArr) {
      return ListView.separated(
        itemCount: dataArr.length,
        physics: const NeverScrollableScrollPhysics(),
        itemBuilder: (BuildContext context, int index) {
          return GestureDetector(onTap: () {Navigator.pop(context);
                if (clickCallback != null) {clickCallback(index, listData[index]);
                }
              },
              child: Container(
                height: cellHeight,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[selText==dataArr[index]?
                    Text(dataArr[index], style: TextStyle(fontSize: 16,color:
                    Colors.blue)):Text(dataArr[index], style: TextStyle(fontSize: 16))
                  ],
                ),
              ));
        },
        separatorBuilder: (context, index) {
          return Divider(
            height: 0.1,
            color: Color(0xFFE6E6E6),
          );
        },
      );
    }

    _buildMenusView(dataArr) {
      var cellH = dataArr.length * cellHeight;
      var navH = ScreenUtils.navigationBarHeight;
      navH = navH - ScreenUtils.topSafeHeight;
      var leftP=(ScreenUtils.screenWidth-cellWidth)/2;
      return Positioned(
        left: leftP,
        top: navH-10,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            Container(padding: EdgeInsets.only(right: 10),
              child: TriangleUpWidget(height: 10,width: 14),
            ),
            ClipRRect(borderRadius: BorderRadius.circular(2),
                child: Container(
                    color: _bgColor,
                    width: cellWidth,
                    height: cellH,
                    child: _buildMenuLineCell(dataArr)))
          ],
        ),
      );
    }

    showDialog(
        context: context,
        barrierDismissible: false,
        builder: (context) {return BasePopMenus(child: _buildMenusView(listData));
        });
  }
}

class BasePopMenus extends Dialog {
  BasePopMenus({
    Key key,
    this.child,
  }) : super(key: key);

  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Material(
      type: MaterialType.transparency,
      child: Stack(
        fit: StackFit.expand,
        children: <Widget>[GestureDetector(onTap: () => Navigator.pop(context)),
          child
        ],
      ),
    );
  }
}

如果须要扭转弹框的地位,能够批改_buildMenusView() 办法中的 Positioned 组件的边距代码。下面的代码中用到了一个自定义三角形,代码如下。

class TriangleUpPainter extends CustomPainter {

  Color color; // 填充色彩
  Paint _paint; // 画笔
  Path _path; // 绘制门路
  double angle; // 角度

  TriangleUpPainter() {_paint = Paint()
      ..strokeWidth = 1.0 // 线宽
      ..color = Colors.white
      ..isAntiAlias = true;
    _path = Path();}

  @override
  void paint(Canvas canvas, Size size) {
    final baseX = size.width;
    final baseY = size.height;
    // 终点
    _path.moveTo(baseX*0.5, 0);
    _path.lineTo(baseX, baseY);
    _path.lineTo(0, baseY);
    canvas.drawPath(_path, _paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {return false;}
}

class TriangleUpWidget extends StatefulWidget {
  double height;
  double width;

  TriangleUpWidget({Key key, this.height = 14, this.width = 16}) : super(key:
  key);

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

class CoreTriangleState extends State<TriangleUpWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
        height: widget.height,
        width: widget.width,
        child: CustomPaint(painter: TriangleUpPainter(),
        ));
  }
}

最初,在须要弹框的中央,调用咱们自定义的弹框组件即可,如下所示。

PopMenus.showPop(context: context, listData: segmentLists,
      selText: selectedTab, clickCallback: (int index, String value){});
退出移动版