在这里插入图片描述

前言

在上一篇文章中,我们完成了项目的初始化和环境搭建。本文将深入实现应用的主屏幕框架和底部导航栏,这是整个应用的核心架构。我们将使用真实的项目代码,逐步构建一个功能完整的主界面。

主屏幕架构设计在这里插入图片描述

整体结构分析

我们的三国杀攻略App采用经典的底部导航栏设计,包含四个主要模块:武将攻略工具社区。每个模块都有独立的功能区域,通过底部导航栏进行切换。

import 'package:flutter/material.dart';
import 'package:convex_bottom_bar/convex_bottom_bar.dart';
import 'tabs/heroes_tab.dart';
import 'tabs/strategy_tab.dart';
import 'tabs/tools_tab.dart';
import 'tabs/community_tab.dart';

这里我们引入了必要的依赖包。ConvexAppBar 是一个优秀的底部导航栏库,它提供了炫酷的凸起效果和流畅的动画。相比传统的 BottomNavigationBar,它在视觉效果上更加出色,特别适合游戏类应用。

主屏幕类定义

class MainScreen extends StatefulWidget {
  const MainScreen({Key? key}) : super(key: key);

  
  State<MainScreen> createState() => _MainScreenState();
}

我们使用 StatefulWidget 来管理主屏幕的状态,这样可以响应用户的导航切换操作。const 构造函数的使用是一个重要的性能优化点,它告诉 Flutter 这个 widget 是不可变的,可以被缓存复用。

状态管理实现

class _MainScreenState extends State<MainScreen> {
  int _currentIndex = 0;

  final List<Widget> _tabs = [
    const HeroesTab(),
    const StrategyTab(),
    const ToolsTab(),
    const CommunityTab(),
  ];

这里定义了两个关键变量:_currentIndex 用于跟踪当前选中的标签页索引,_tabs 列表存储了所有的标签页 widget。使用 final 关键字确保列表在初始化后不会被重新赋值,这是一个良好的编程习惯。

主界面构建


Widget build(BuildContext context) {
  return Scaffold(
    body: _tabs[_currentIndex],
    bottomNavigationBar: ConvexAppBar(
      backgroundColor: const Color(0xFF8B0000),
      style: TabStyle.reactCircle,
      items: const [
        TabItem(icon: Icons.people, title: '武将'),
        TabItem(icon: Icons.book, title: '攻略'),
        TabItem(icon: Icons.build, title: '工具'),
        TabItem(icon: Icons.forum, title: '社区'),
      ],
      initialActiveIndex: _currentIndex,
      onTap: (index) {
        setState(() {
          _currentIndex = index;
        });
      },
    ),
  );
}

这是主界面的核心构建方法。Scaffold 提供了基本的页面结构,body 部分显示当前选中的标签页内容。ConvexAppBar 的配置中,我们使用了深红色 #8B0000 作为背景色,这个颜色很好地契合了三国杀的主题风格。TabStyle.reactCircle 样式提供了圆形的反应式效果,当用户点击时会有优雅的动画。

武将标签页实现

基础结构搭建

class HeroesTab extends StatelessWidget {
  const HeroesTab({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('武将大全'),
        actions: [
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () => Get.to(() => const HeroSearchScreen()),
          ),
          IconButton(
            icon: const Icon(Icons.favorite),
            onPressed: () => Get.to(() => const FavoriteHeroesScreen()),
          ),
        ],
      ),

武将标签页的 AppBar 设计很有特色,除了标题外,还添加了搜索和收藏两个快捷按钮。这种设计让用户可以快速访问常用功能,提升了用户体验。Get.to() 是 GetX 路由管理的方法,相比传统的 Navigator.push(),它更加简洁易用。

横幅区域设计

Widget _buildBanner() {
  return Container(
    height: 180.h,
    margin: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [Color(0xFF8B0000), Color(0xFFDC143C)],
      ),
      borderRadius: BorderRadius.circular(12.r),
    ),
    child: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            '三国杀武将图鉴',
            style: TextStyle(
              color: Colors.white,
              fontSize: 24.sp,
              fontWeight: FontWeight.bold,
            ),
          ),
          SizedBox(height: 8.h),
          Text(
            '共收录 ${model.HeroData.getAllHeroes().length} 名武将',
            style: TextStyle(color: Colors.white70, fontSize: 14.sp),
          ),
        ],
      ),
    ),
  );
}

横幅区域使用了渐变背景,从深红色过渡到鲜红色,营造出浓厚的三国氛围。这里使用了 flutter_screenutil 进行屏幕适配,.h.w.sp.r 分别代表高度、宽度、字体大小和圆角的适配单位。动态显示武将数量是一个很好的细节,让用户了解应用的内容丰富程度。

快速访问网格

Widget _buildQuickAccess() {
  final items = [
    {'icon': Icons.list, 'title': '武将列表', 'screen': const HeroListScreen()},
    {'icon': Icons.compare_arrows, 'title': '武将对比', 'screen': const HeroCompareScreen()},
    {'icon': Icons.leaderboard, 'title': '强度排行', 'screen': const HeroTierScreen()},
    {'icon': Icons.shield, 'title': '克制关系', 'screen': const HeroCounterScreen()},
    {'icon': Icons.group_work, 'title': '配合推荐', 'screen': const HeroComboScreen()},
  ];

快速访问区域采用了网格布局,每个功能都有对应的图标和标题。这种设计让用户可以一目了然地看到所有可用功能,提高了应用的易用性。图标的选择也很有意义:compare_arrows 表示对比,leaderboard 表示排行,shield 表示克制关系等。

势力分类展示

Widget _buildCountrySection() {
  final countries = [
    {'name': '蜀', 'color': const Color(0xFFFF6B6B), 'count': 7},
    {'name': '魏', 'color': const Color(0xFF4ECDC4), 'count': 7},
    {'name': '吴', 'color': const Color(0xFF95E1D3), 'count': 8},
    {'name': '群', 'color': const Color(0xFFF38181), 'count': 3},
  ];

势力分类使用了不同的主题色彩来区分各个国家,这种视觉设计让用户可以快速识别不同势力。颜色的选择也很考究:蜀国用红色系,魏国用青色系,吴国用绿色系,群雄用粉色系,既有区分度又保持了整体的和谐感。

攻略标签页实现

头部设计

Widget _buildHeader() {
  return Container(
    height: 150.h,
    margin: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [Color(0xFF2C3E50), Color(0xFF3498DB)],
      ),
      borderRadius: BorderRadius.circular(12.r),
    ),
    child: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.book, size: 48.sp, color: Colors.white),
          SizedBox(height: 8.h),
          Text(
            '从新手到高手',
            style: TextStyle(
              color: Colors.white,
              fontSize: 20.sp,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    ),
  );
}

攻略标签页的头部采用了蓝色渐变,与武将页面的红色形成对比,让用户能够清楚地区分不同模块。"从新手到高手"这个标语很好地概括了攻略内容的定位,给用户明确的期望。

攻略分类实现

Widget _buildStrategyCategories() {
  final categories = [
    {'icon': Icons.school, 'title': '新手入门', 'desc': '基础规则与玩法', 'screen': const BeginnerGuideScreen()},
    {'icon': Icons.style, 'title': '卡牌详解', 'desc': '所有卡牌效果说明', 'screen': const CardGuideScreen()},
    {'icon': Icons.people, 'title': '身份攻略', 'desc': '主忠反内玩法技巧', 'screen': const IdentityStrategyScreen()},
    {'icon': Icons.star, 'title': '进阶技巧', 'desc': '高级战术与心理', 'screen': const AdvancedTipsScreen()},
  ];

攻略分类的设计遵循了从易到难的学习路径,从新手入门开始,逐步深入到高级技巧。每个分类都有清晰的描述,帮助用户快速找到需要的内容。图标的选择也很直观:school 代表学习,style 代表卡牌,people 代表身份等。

工具标签页实现

工具网格布局

Widget _buildToolsGrid() {
  final tools = [
    {'icon': Icons.calculate, 'title': '伤害计算器', 'desc': '计算伤害与血量', 'screen': const DamageCalculatorScreen()},
    {'icon': Icons.percent, 'title': '概率计算', 'desc': '判定成功率计算', 'screen': const ProbabilityCalculatorScreen()},
    {'icon': Icons.style, 'title': '卡组构建', 'desc': '自定义卡组工具', 'screen': const DeckBuilderScreen()},
    {'icon': Icons.timer, 'title': '回合计时器', 'desc': '控制游戏节奏', 'screen': const TimerScreen()},
  ];

工具标签页采用了2列网格布局,每个工具都有明确的功能描述。这些工具都是三国杀玩家在实际游戏中经常需要的辅助功能,比如伤害计算器可以帮助玩家快速计算复杂的伤害结果,概率计算器可以分析各种判定的成功率。

绿色主题设计

decoration: BoxDecoration(
  gradient: const LinearGradient(
    colors: [Color(0xFF16A085), Color(0xFF27AE60)],
  ),
  borderRadius: BorderRadius.circular(12.r),
),

工具模块使用了绿色渐变作为主题色,绿色通常代表实用性和稳定性,很适合工具类功能的定位。这种颜色选择让用户在视觉上就能感受到这是一个实用的功能区域。

社区标签页实现

用户信息卡片

Widget _buildUserCard() {
  return Container(
    margin: EdgeInsets.all(16.w),
    padding: EdgeInsets.all(20.w),
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [Color(0xFF8E44AD), Color(0xFF9B59B6)],
      ),
      borderRadius: BorderRadius.circular(12.r),
    ),
    child: Row(
      children: [
        CircleAvatar(
          radius: 30.r,
          backgroundColor: Colors.white,
          child: Icon(Icons.person, size: 35.sp, color: const Color(0xFF8E44AD)),
        ),

社区标签页的用户信息卡片使用了紫色渐变,紫色给人一种神秘和高贵的感觉,很适合社区功能的定位。CircleAvatar 组件创建了圆形的用户头像区域,这是现代应用中常见的设计模式。

社区功能网格

Widget _buildCommunityFeatures() {
  final features = [
    {'icon': Icons.forum, 'title': '讨论区', 'desc': '与玩家交流心得', 'screen': const ForumScreen()},
    {'icon': Icons.share, 'title': '分享战绩', 'desc': '晒出精彩对局', 'screen': const ShareScreen()},
    {'icon': Icons.leaderboard, 'title': '排行榜', 'desc': '查看高手排名', 'screen': const RankingScreen()},
    {'icon': Icons.event, 'title': '活动中心', 'desc': '参与官方活动', 'screen': const EventsScreen()},
  ];

社区功能采用了2x2网格布局,包含了现代社交应用的核心功能:讨论、分享、排行和活动。这种布局既保证了功能的完整性,又不会让界面显得过于拥挤。

底部导航栏深度定制

ConvexAppBar 样式配置

ConvexAppBar(
  backgroundColor: const Color(0xFF8B0000),
  style: TabStyle.reactCircle,
  items: const [
    TabItem(icon: Icons.people, title: '武将'),
    TabItem(icon: Icons.book, title: '攻略'),
    TabItem(icon: Icons.build, title: '工具'),
    TabItem(icon: Icons.forum, title: '社区'),
  ],
  initialActiveIndex: _currentIndex,
  onTap: (index) {
    setState(() {
      _currentIndex = index;
    });
  },
),

ConvexAppBar 的配置中,TabStyle.reactCircle 提供了圆形的反应式效果,当用户点击时会有优雅的动画过渡。onTap 回调函数使用 setState 来更新当前选中的标签索引,这是 Flutter 中最基本的状态管理方式。

屏幕适配方案

return ScreenUtilInit(
  designSize: const Size(375, 812),
  minTextAdapt: true,
  splitScreenMode: true,
  builder: (context, child) {
    return GetMaterialApp(
      title: '三国杀攻略',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.red,
        scaffoldBackgroundColor: const Color(0xFFF5F5F5),
      ),
      home: const MainScreen(),
    );
  },
);

ScreenUtilInit 的配置基于 iPhone X 的尺寸 375x812,这是目前最常用的设计基准。minTextAdapt 确保文字在小屏幕上也能保持可读性,splitScreenMode 支持分屏模式。这种适配方案可以确保应用在不同尺寸的设备上都有良好的显示效果。

性能优化策略

使用 const 构造函数

const TabItem(icon: Icons.people, title: '武将'),
const HeroesTab(),
const StrategyTab(),

在 Flutter 中,const 构造函数是一个重要的性能优化手段。它告诉 Flutter 这些 widget 是不可变的,可以被缓存和复用,避免不必要的重建。这在底部导航栏这种频繁切换的场景中特别重要。

状态保持机制

class _HeroesTabState extends State<HeroesTab> 
    with AutomaticKeepAliveClientMixin {
  
  
  bool get wantKeepAlive => true;

  
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(...);
  }
}

AutomaticKeepAliveClientMixin 可以让标签页在切换时保持状态,避免重复加载数据。这对于包含列表或复杂内容的页面特别有用,可以显著提升用户体验。

主题色彩设计理念

我们为每个模块都设计了独特的主题色彩:

  • 武将模块:深红色 #8B0000,象征着战斗和力量
  • 攻略模块:蓝色系 #3498DB,代表智慧和策略
  • 工具模块:绿色系 #27AE60,表示实用和稳定
  • 社区模块:紫色系 #9B59B6,体现社交和互动

这种色彩分区的设计让用户可以快速识别不同的功能模块,提升了应用的易用性和专业感。

响应式布局实现

GridView.builder(
  shrinkWrap: true,
  physics: const NeverScrollableScrollPhysics(),
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    childAspectRatio: 1.2,
    crossAxisSpacing: 12.w,
    mainAxisSpacing: 12.h,
  ),

GridView.builder 的配置中,shrinkWrap: true 让网格视图只占用必要的空间,NeverScrollableScrollPhysics() 禁用了网格的滚动,因为我们希望整个页面作为一个整体滚动。childAspectRatio: 1.2 设置了网格项的宽高比,确保在不同屏幕上都有良好的显示效果。

导航路由管理

onPressed: () => Get.to(() => const HeroSearchScreen()),

我们使用 GetX 进行路由管理,相比传统的 Navigator.push(),GetX 提供了更简洁的 API 和更强大的功能。Get.to() 方法可以直接跳转到目标页面,无需复杂的路由配置。

用户体验优化

视觉反馈设计

boxShadow: [
  BoxShadow(
    color: Colors.black.withOpacity(0.05),
    blurRadius: 8,
    offset: const Offset(0, 2),
  ),
],

我们为所有的卡片组件都添加了轻微的阴影效果,这种设计让界面更有层次感,提升了视觉体验。阴影的透明度设置为 0.05,既能提供视觉层次,又不会过于突兀。

交互动画效果

GestureDetector(
  onTap: () => Get.to(() => item['screen'] as Widget),
  child: Container(
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(12.r),
    ),

GestureDetector 包装的容器提供了点击交互,配合 BorderRadius.circular(12.r) 的圆角设计,让整个界面更加现代化和友好。

总结

通过本文的详细实现,我们构建了一个功能完整、设计精美的主屏幕框架。这个框架不仅包含了四个主要功能模块,还实现了优雅的底部导航栏、响应式布局、主题色彩设计等多个方面的优化。

关键技术点回顾

  • 使用 ConvexAppBar 实现炫酷的底部导航效果
  • 通过 flutter_screenutil 实现完美的屏幕适配
  • 采用模块化的色彩设计提升用户体验
  • 运用 GetX 简化路由管理
  • 通过性能优化确保应用流畅运行

在下一篇文章中,我们将深入实现武将数据模型的设计,为整个应用的数据架构打下坚实基础。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐