12.1 商品界面初始
实现步骤:
第 1 步:i18n
1 2 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
1 2 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
1 2 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
1 2 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
1 2 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: (_) {
 
  | 
 
1 2 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
1 2 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
1 2 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
1 2 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
1 2 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 视图"); }
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   |  Widget _buildView() {   return <Widget>[                      _buildBanner(),
                       _buildTitle(),
                       _buildTabBar(),
                       _buildTabView(),         ].toColumn(); }
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | @override Widget 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