在挪动开发中,下拉弹框是一种很常见的抉择交互方式,成果如下图所示。
对于这种弹框,咱们能够应用 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){});