14.2 排序规则下拉栏

14.2 排序规则下拉栏

img

实现步骤:


第 1 步:安装插件 dropdown_button2

1
flutter pub add dropdown_button2

第 2 步:DropdownWidget 组件编写

lib/common/components/dropdown.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import 'package:flutter/material.dart';
import 'package:dropdown_button2/dropdown_button2.dart';

import '../index.dart';

/// 下拉菜单
class DropdownWidget extends StatelessWidget {
/// 点击菜单
final Function(KeyValueModel? val)? onChanged;

/// 数据项列表
final List<KeyValueModel>? items;

/// 选中数据值
final KeyValueModel? selectedValue;

/// 提示文字
final String? hintText;

/// 图标颜色
final Color? iconColor;

/// 按钮 padding
final EdgeInsetsGeometry? buttonPadding;

const DropdownWidget({
Key? key,
this.items,
this.selectedValue,
this.hintText,
this.onChanged,
this.buttonPadding,
this.iconColor,
}) : super(key: key);

Widget _buildView() {
return DropdownButtonHideUnderline(
child: DropdownButton2<KeyValueModel>(
// 扩展
isExpanded: true,
// 提示组件
hint: Row(
children: [
Expanded(
child: TextWidget.body1(hintText ?? 'Select Item'),
),
],
),
// 下拉项列表
items: items
?.map((item) => DropdownMenuItem<KeyValueModel>(
value: item,
child: TextWidget.body1(item.value),
))
.toList(),
// 选中项
value: selectedValue,
// 改变事件
onChanged: onChanged,
// 图标
icon: IconWidget.icon(
Icons.expand_more,
color: iconColor ?? AppColors.primary,
),
// 按钮 padding
buttonPadding: buttonPadding ??
EdgeInsets.symmetric(horizontal: AppSpace.iconTextSmail),
// 偏移
offset: const Offset(0, 0),
),
);
}

@override
Widget build(BuildContext context) {
return _buildView();
}
}

第 3 步:控制器

lib/pages/search/search_filter/controller.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
// 排序列表
List<KeyValueModel> orderList = [
KeyValueModel(key: "rating", value: "Best Match"),
KeyValueModel(key: "price_low", value: "Price (low to high)"),
KeyValueModel(key: "price_high", value: "Price (high to low)"),
KeyValueModel(key: "popularity", value: "Popularity"),
KeyValueModel(key: "date", value: "New publish"),
KeyValueModel(key: "title", value: "Product name"),
KeyValueModel(key: "slug", value: "Slug name"),
];
// 排序选中
KeyValueModel orderSelected =
KeyValueModel(key: "rating", value: "Best Match");
1
2
3
4
5
// 排序选中
void onOrderTap(KeyValueModel? val) {
orderSelected = val!;
update(["search_filter"]);
}

第 4 步:按钮加入 Dropdown 类型

lib/common/widgets/button.dart

1
2
3
4
enum ButtonWidgetType {
...
dropdown, // 文字/图标/两端对齐
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/// 文字 / 图标 / dropdown
ButtonWidget.dropdown(
this.text,
this.icon, {
Key? key,
Color? textColor,
double? textSize,
FontWeight? textWeight,
this.type = ButtonWidgetType.dropdown,
this.onTap,
this.borderRadius = 0,
this.backgroundColor,
this.borderColor,
this.width,
this.height,
}) : child = <Widget>[
TextWidget.button(
text: text!,
size: textSize,
color: textColor ?? AppColors.onPrimaryContainer,
weight: textWeight,
).expanded(),
icon!,
]
.toRow(
mainAxisSize: MainAxisSize.min,
)
.paddingHorizontal(AppSpace.button),
super(key: key);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 边框
MaterialStateProperty<BorderSide?>? get _side {
switch (type) {
case ButtonWidgetType.secondary:
return MaterialStateProperty.all(BorderSide(
color: borderColor ?? AppColors.primary,
width: 1,
));
case ButtonWidgetType.iconTextOutlined:
case ButtonWidgetType.iconTextUpDownOutlined:
case ButtonWidgetType.dropdown:
return MaterialStateProperty.all(BorderSide(
color: borderColor ?? AppColors.outline,
width: 1,
));
default:
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 形状圆角
MaterialStateProperty<OutlinedBorder?>? get _shape {
switch (type) {
...
case ButtonWidgetType.dropdown:
case ButtonWidgetType.textRoundFilled:
return MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(borderRadius ?? 0)),
),
);
default:
return null;
}
}

第 5 步:视图

lib/pages/search/search_filter/view.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 搜索过滤栏
Widget _buildFilterBar() {
return <Widget>[
// 排序 Best Match
DropdownWidget(
items: controller.orderList,
hintText: controller.orderSelected.value,
onChanged: controller.onOrderTap,
)
.decorated(
border: Border.all(
color: AppColors.surfaceVariant,
width: 1,
),
)
.height(40.h)
.expanded(),

// 筛选 Filter
ButtonWidget.dropdown(
LocaleKeys.searchFilter.tr,
IconWidget.icon(
Icons.expand_more,
color: AppColors.primary,
),
// onTap: controller.onFilterOpenTap,
textSize: 15,
textColor: AppColors.secondary,
textWeight: FontWeight.w400,
borderColor: AppColors.surfaceVariant,
height: 40.h,
).expanded(),
].toRow();
}

提交代码到 git