全屏幕menu弹框,可以设置位置,居中,居左,居右,居顶,居底部。默认右上角位置
import 'dart:math' as math;
import 'dart:ui' as ui show window;
import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';
import 'package:supercharged/supercharged.dart';
class FSMenuPopModel {
String? title;
String? id;
String? icon;
bool selected; // 是否选中
FSMenuPopModel({
this.title,
this.id,
this.selected = false,
this.icon,
});
}
enum FSMenuLayoutType {
left, //从左开始
xCenter,
right, //从右开始
top, //从上开始
yCenter,
bottom, //从下开始
}
/**
* example:
FSMenuPopModel currentModel = FSMenuPopModel();
showPop() {
List list = [];
for (int i = 0; i < 5; i++){
FSMenuPopModel model1 = FSMenuPopModel();
model1.title = '排序'+i.toString();
model1.id = (100 + i).toString();
model1.icon = R.assetsImgCommonQiehuan;
model1.selected = model1.id == currentModel.id;
list.add(model1);
}
DialogUtil.showMaskView(
FSMenuPopView(
itemList: list,
xLayoutType: FSMenuLayoutType.right,
// yLayoutType: NavMenuLayoutType.yCenter,
activeBackground: StyleColor.theme_light_gray,
yMargin: 10 + ScreenUtil.getAppBarHeight,
onTap: (FSMenuPopModel model) async {
currentModel = model;
NavigatorUtil.pop();
},
),
backgroundColor: Colors.black.withAlpha(0)
);
}
* */
/// 选择menu
class FSMenuPopView extends StatefulWidget {
final ValueSetter? onTap; //点击回调方法
final List? itemList;
final Color? menuBackground;
final Color? normalBackground;
final Color? activeBackground;
final double? borderRadius;
final double? horizontalSpace; //左右边距
final double? itemVerticalSpace; //上下边距
final double? imgWidth;
TextStyle? activeTextStyle;
TextStyle? normalTextStyle;
///定位,默认右上角弹出
final FSMenuLayoutType? yLayoutType; //y定位类型,默认从顶部
final FSMenuLayoutType? xLayoutType; //x定位类型,默认从右侧
final double? xMargin; //距离左右定位的边距,需结合xLayoutType枚举使用
final double? yMargin; //距离上下定位的边距,需结合yLayoutType枚举使用
FSMenuPopView({
@required this.onTap,
@required this.itemList,
this.xMargin,
this.yMargin,
this.xLayoutType,
this.yLayoutType,
this.menuBackground = Colors.white,
this.normalBackground = Colors.white,
this.activeBackground = Colors.white,
this.activeTextStyle,
this.normalTextStyle,
this.borderRadius = 5,
this.imgWidth = 15,
this.horizontalSpace,
this.itemVerticalSpace,
});
@override
_FSMenuViewState createState() => _FSMenuViewState();
}
class _FSMenuViewState extends State {
// 获取状态栏高度
static final MediaQueryData _mediaQueryData = MediaQueryData.fromWindow(ui.window);
static double get _getStatusBarHeight => _mediaQueryData.padding.top;
//内容距离视图左右默认边距
double get _defaultSpaceHorizontal => 20;
//内容距离视图上下默认边距
double get _defaultSpaceVertical => 10;
TextStyle get _activeDefaultTextStyle => TextStyle(color: Colors.black, fontSize: 16);
TextStyle get _normalDefaultTextStyle => TextStyle(color: Color(0xFF595961), fontSize: 16);
//y布局
double get _defaultYMargin => _getStatusBarHeight;
FSMenuLayoutType get _defaultLayoutTypeY => FSMenuLayoutType.top;
//x布局
double get _defaultXMargin => 20;
FSMenuLayoutType get _defaultLayoutTypeX => FSMenuLayoutType.right;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
decoration: BoxDecoration(
color: Colors.black.withAlpha(0),
),
child: PlayAnimation(
tween: 0.0.tweenTo(1.0),
duration: 300.milliseconds,
curve: Curves.easeOut,
builder: (context, child, value) {
return Transform.scale(
scale: value,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
//顶部占位视图
(widget.yLayoutType ?? _defaultLayoutTypeY) == FSMenuLayoutType.top
? Container(height: widget.yMargin ?? _defaultYMargin)
: Expanded(
child: Container(
color: Colors.black.withAlpha(0),
)),
Row(
mainAxisSize: MainAxisSize.max,
children: [
//左侧占位视图
(widget.xLayoutType ?? _defaultLayoutTypeX) == FSMenuLayoutType.left
? Container(width: widget.xMargin ?? _defaultXMargin)
: Expanded(child: Container()),
//内容
_contentWidget,
//右侧占位视图
(widget.xLayoutType ?? _defaultLayoutTypeX) == FSMenuLayoutType.right
? Container(width: widget.xMargin ?? _defaultXMargin)
: Expanded(child: Container()),
],
),
//底部占位视图
(widget.yLayoutType ?? _defaultLayoutTypeY) == FSMenuLayoutType.bottom
? Container(height: widget.yMargin ?? _defaultYMargin)
: Expanded(child: Container()),
],
),
);
},
),
),
);
}
/// 界面
Widget get _contentWidget {
return Container(
clipBehavior: Clip.antiAlias,
decoration: new BoxDecoration(
color: widget.menuBackground ?? Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(widget.borderRadius ?? 0),
),
boxShadow: [
BoxShadow(
offset: Offset(4.0, 4.0),
blurRadius: 10,
color: Color(0xFFF2F2F6),
)
],
),
child: Column(
children: (widget.itemList ?? []).map((item) {
return GestureDetector(
onTap: () {
if (widget.onTap != null) widget.onTap!(item);
},
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: item == (widget.itemList ?? []).last
? BorderSide.none
: BorderSide(
width: 1,
color: Color(0xFFEFEFEF),
),
),
),
child: Container(
padding: EdgeInsets.symmetric(
vertical: (widget.itemVerticalSpace ?? _defaultSpaceVertical),
horizontal: (widget.horizontalSpace ?? _defaultSpaceHorizontal),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Offstage(
offstage: item.icon == null || item.icon!.isEmpty,
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Image.asset(
item.icon ?? '',
width: widget.imgWidth,
height: widget.imgWidth,
),
),
),
Text(
item.title ?? '',
textAlign: TextAlign.center,
style: item.selected == true ? (widget.activeTextStyle ?? _activeDefaultTextStyle) : (widget.normalTextStyle ?? _normalDefaultTextStyle),
),
],
),
decoration: BoxDecoration(
color: item.selected == true ? widget.activeBackground : widget.normalBackground,
),
),
),
);
}).toList(),
),
);
}
}