11.1 左侧导航栏组件

11.1 左侧导航栏组件

效果

img

实现步骤:


第 1 步:i18n

lib/common/i18n/locale_keys.dart

1
2
// 商品 - 分类
static const gCategoryTitle = "goods_category_title";

lib/common/i18n/locales/locale_en.dart

1
2
// 商品 - 分类页
LocaleKeys.gCategoryTitle: 'All Categories',

lib/common/i18n/locales/locale_zh.dart

1
2
// 商品 - 分类
LocaleKeys.gCategoryTitle: '所有分类',

第 2 步:分类数据缓存读取

lib/common/values/constants.dart

1
2
3
// 基础数据
// 商品分类
static const storageProductsCategories = 'home_categories';

lib/pages/goods/home/controller.dart

1
2
3
4
// 初始数据,从网络拉取
Future<void> _initData() async {
// 保存离线数据
Storage().setJson(Constants.storageProductsCategories, categoryItems);

第 3 步:控制器

lib/pages/goods/category/controller.dart

1
2
// 分类 id , 获取路由传递参数
int? categoryId = Get.arguments['id'];
1
2
// 分类导航数据
List<CategoryModel> categoryItems = [];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 初始数据
_initData() async {
// 读缓存
var stringCategories =
Storage().getString(Constants.storageProductsCategories);
categoryItems = stringCategories != ""
? jsonDecode(stringCategories).map<CategoryModel>((item) {
return CategoryModel.fromJson(item);
}).toList()
: [];

// 如果本地缓存空
if (categoryItems.isEmpty) {
categoryItems = await ProductApi.categories(); // 获取分类数据
}

update(["left_nav"]);
}
1
2
3
4
5
// 分类点击事件
void onCategoryTap(int id) async {
categoryId = id;
update(["left_nav"]);
}

第 4 步:视图

lib/pages/goods/category/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
35
// 左侧导航
Widget _buildLeftNav() {
return GetBuilder<CategoryController>(
id: "left_nav", // 唯一标识
builder: (_) {
return ListView.separated(
itemBuilder: (context, index) {
var item = controller.categoryItems[index]; // 分类项数据
return CategoryListItemWidget(
category: item, // 分类数据
selectId: controller.categoryId, // 选中代码
onTap: controller.onCategoryTap, // tap 事件
);
},
separatorBuilder: (context, index) {
return SizedBox(height: AppSpace.listRow.w); // 间距
},
itemCount: controller.categoryItems.length, // 分类项数量
)
// 指定高度 100
.width(100.w)

// 背景色
.decorated(
color: AppColors.surfaceVariant,
)

// 右上,右下 裁剪圆角
.clipRRect(
topRight: AppRadius.card.w,
bottomRight: AppRadius.card.w,
);
},
);
}
1
2
3
4
5
6
7
8
// 主视图
Widget _buildView() {
return <Widget>[
// 左侧导航
_buildLeftNav(),
// 右侧商品列表
].toRow();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@override
Widget build(BuildContext context) {
return GetBuilder<CategoryController>(
init: CategoryController(),
id: "category",
builder: (_) {
return Scaffold(
// 顶部导航
appBar: mainAppBarWidget(
titleString: LocaleKeys.gCategoryTitle.tr,
),
// 内容
body: SafeArea(
child: _buildView(),
),
);
},
);
}

第 5 步:首页分类点击

lib/pages/goods/home/controller.dart

1
2
3
4
5
6
7
8
9
// 分类点击事件
void onCategoryTap(int categoryId) {
Get.toNamed(
RouteNames.goodsCategory,
arguments: {
"id": categoryId,
},
);
}

提交代码到 git