12.1 商品界面初始
 
实现步骤:
第 1 步:i18n
| 12
 3
 4
 5
 6
 7
 
 | static const gDetailTitle = "goods_detail_title";
 static const gDetailTabProduct = "goods_detail_tab_product";
 static const gDetailTabDetails = "goods_detail_tab_details";
 static const gDetailTabReviews = "goods_detail_tab_reviews";
 static const gDetailBtnAddCart = "goods_detail_btn_add_cart";
 static const gDetailBtnBuy = "goods_detail_btn_buy";
 
 | 
lib/common/i18n/locales/locale_en.dart
| 12
 3
 4
 5
 6
 7
 
 | LocaleKeys.gDetailTitle: 'Product Info',
 LocaleKeys.gDetailTabProduct: 'Product',
 LocaleKeys.gDetailTabDetails: 'Details',
 LocaleKeys.gDetailTabReviews: 'Reviews',
 LocaleKeys.gDetailBtnAddCart: 'Add To Cart',
 LocaleKeys.gDetailBtnBuy: 'Buy Now',
 
 | 
lib/common/i18n/locales/locale_zh.dart
| 12
 3
 4
 5
 6
 7
 
 | LocaleKeys.gDetailTitle: '商品信息',
 LocaleKeys.gDetailTabProduct: '规格',
 LocaleKeys.gDetailTabDetails: '说明',
 LocaleKeys.gDetailTabReviews: '评论',
 LocaleKeys.gDetailBtnAddCart: '加入购物车',
 LocaleKeys.gDetailBtnBuy: '立刻购买',
 
 | 
第 2 步:Stateful + GetX 结构
goods 目录右键菜单创建
 
默认状态保持开启 wantKeepAlive => true
lib/pages/goods/product_details/controller.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | class ProductDetailsPage extends StatefulWidget {
 const ProductDetailsPage({Key? key}) : super(key: key);
 
 @override
 State<ProductDetailsPage> createState() => _ProductDetailsPageState();
 }
 
 class _ProductDetailsPageState extends State<ProductDetailsPage>
 with AutomaticKeepAliveClientMixin {
 @override
 bool get wantKeepAlive => true;
 
 
 | 
第 3 步:tag 区分商品页
lib/pages/goods/product_details/view.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | class _ProductDetailsGetx extends GetView<ProductDetailsController> {
 final String uniqueTag;
 
 
 const _ProductDetailsGetx(this.uniqueTag, {Key? key}) : super(key: key);
 
 
 @override
 String? get tag => uniqueTag;
 
 ...
 
 @override
 Widget build(BuildContext context) {
 return GetBuilder<ProductDetailsController>(
 init: ProductDetailsController(),
 id: "product_details",
 
 tag: tag,
 builder: (_) {
 
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | class _ProductDetailsPageState extends State<ProductDetailsPage>with AutomaticKeepAliveClientMixin {
 @override
 bool get wantKeepAlive => true;
 
 
 final String tag = '${Get.arguments['id'] ?? ''}${UniqueKey()}';
 
 @override
 Widget build(BuildContext context) {
 super.build(context);
 
 
 return _ProductDetailsGetx(tag);
 }
 }
 
 | 
通过 tag 属性 进行区分不同商品控制器 Controller
第 4 步:子组件
商品规格
lib/pages/goods/product_details/widgets/tab_product.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | import 'package:flutter/material.dart';import 'package:get/get.dart';
 
 import '../index.dart';
 
 
 class TabProductView extends GetView<ProductDetailsController> {
 final String uniqueTag;
 
 const TabProductView({Key? key, required this.uniqueTag}) : super(key: key);
 
 @override
 String? get tag => uniqueTag;
 
 @override
 Widget build(BuildContext context) {
 return const Text("商品规格");
 }
 }
 
 | 
商品详情
lib/pages/goods/product_details/widgets/tab_detail.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | import 'package:flutter/material.dart';import 'package:get/get.dart';
 
 import '../index.dart';
 
 
 class TabDetailView extends GetView<ProductDetailsController> {
 final String uniqueTag;
 
 const TabDetailView({Key? key, required this.uniqueTag}) : super(key: key);
 
 @override
 String? get tag => uniqueTag;
 
 @override
 Widget build(BuildContext context) {
 return const Text("商品详情");
 }
 }
 
 | 
商品评论
lib/pages/goods/product_details/widgets/tab_reviews.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | import 'package:flutter/material.dart';import 'package:get/get.dart';
 
 import '../index.dart';
 
 
 class TabReviewsView extends GetView<ProductDetailsController> {
 final String uniqueTag;
 
 const TabReviewsView({Key? key, required this.uniqueTag}) : super(key: key);
 
 @override
 String? get tag => uniqueTag;
 
 @override
 Widget build(BuildContext context) {
 return const Text("评论");
 }
 }
 
 
 | 
第 5 步:视图
lib/pages/goods/product_details/view.dart
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | Widget _buildBanner() {
 return Text("滚动图");
 }
 
 
 Widget _buildTitle() {
 return Text("滚动图");
 }
 
 
 Widget _buildTabBar() {
 return Text("Tab 栏位");
 }
 
 
 Widget _buildTabView() {
 return Text("TabView 视图");
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | Widget _buildView() {
 return <Widget>[
 
 _buildBanner(),
 
 
 _buildTitle(),
 
 
 _buildTabBar(),
 
 
 _buildTabView(),
 ].toColumn();
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | @overrideWidget build(BuildContext context) {
 return GetBuilder<ProductDetailsController>(
 init: ProductDetailsController(),
 id: "product_details",
 
 tag: tag,
 builder: (_) {
 return Scaffold(
 
 appBar: mainAppBarWidget(
 titleString:LocaleKeys.gDetailTitle.tr),
 
 body: SafeArea(
 child: _buildView(),
 ),
 );
 },
 );
 }
 
 | 
提交代码到 git