Flutter开发指南(五):实现首页基础布局
通过本文我们完成了组件化的设计。我们将首页拆分为多个独立模块(轮播图、分类、推荐等),每个组件具备独立状态管理能力,使用StatefulWidget实现动态交互。这种架构模式提升了代码复用性和维护效率,符合Flutter声明式UI的开发理念。后续我们将调用API接口渲染到首页的UI上,展示真实的数据。如果有疑问,可以在评论区留言,看到会回答。最后欢迎加入开源鸿蒙跨平台社区:t=PBP8青商城 -
一、项目结构
1.1 组件化设计
何为组件化设计?简单来说,就是把一个页面的内容拆分成多个部分,由多个部分组成一个完整的页面。比如,我们要做的首页,拆分为了五个文件,再由这五个文件组成我们的首页。

1.2 拆分首页组件
在lib/components下新建Home文件夹,分别新建HmSlider.dart文件,HmCategory.dart文件,HmSuggestion.dart文件,HmHot.dart文件,HmmoreList.dart文件

这里输入"stful"即可一键生成代码,然后再命名该文件。

报错是因为没有导入material的包,鼠标悬浮在StatefulWidget,选择蓝色部分导入即可或者直接加入下面这行代码
import 'package:flutter/material.dart';


1.3 新建组件代码示例
HmCatrgory.dart代码
import 'package:flutter/material.dart';
class HmCategory extends StatefulWidget {
const HmCategory({super.key});
@override
State<HmCategory> createState() => _HmCategoryState();
}
class _HmCategoryState extends State<HmCategory> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
HmHot.dart代码
import 'package:flutter/material.dart';
class HmHot extends StatefulWidget {
const HmHot({super.key});
@override
State<HmHot> createState() => _HmHotState();
}
class _HmHotState extends State<HmHot> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
HmMoreList.dart代码
import 'package:flutter/material.dart';
class HmMorelist extends StatefulWidget {
const HmMorelist({super.key});
@override
State<HmMorelist> createState() => _HmMorelistState();
}
class _HmMorelistState extends State<HmMorelist> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
HmSlider.dart代码
import 'package:flutter/material.dart';
class HmSlider extends StatefulWidget {
const HmSlider({super.key});
@override
State<HmSlider> createState() => _HmSliderState();
}
class _HmSliderState extends State<HmSlider> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
HmSuggestion.dart代码
import 'package:flutter/material.dart';
class HmSuggestion extends StatefulWidget {
const HmSuggestion({super.key});
@override
State<HmSuggestion> createState() => _HmSuggestionState();
}
class _HmSuggestionState extends State<HmSuggestion> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
二、编写组件对应代码
以下代码如果想跟文章一步一步探索,只需要书写完成后,只需要在"lib/pages/home/index.dart"
代码中导入对应的组件即可。如果不想跟着文章来,大家也无需担心,在最后会给出修改后完整的代码。
2.1 轮播图组件代码
HmSlider.dart代码
import 'package:flutter/material.dart';
class HmSlider extends StatefulWidget {
const HmSlider({super.key});
@override
State<HmSlider> createState() => _HmSliderState();
}
class _HmSliderState extends State<HmSlider> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
height: 300,
alignment: Alignment.center,
child:
Text('轮播图', style: TextStyle(color: Colors.white, fontSize: 20)));
}
}
Home/index.dart代码
import 'package:flutter/cupertino.dart';
import 'package:qing_mall/components/Home/HmSlider.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
//获取滚动容器的内容
List<Widget> _getScrollChildren() {
return [
//包裹普通widget的sliver家族的组件内容
SliverToBoxAdapter(child: HmSlider()),//轮播图组件
];
}
@override
Widget build(BuildContext context) {
//CustomScrollview要求:必须是sliver家族的内容
return CustomScrollView(slivers: _getScrollChildren());
}
}
完成上述代码后运行到鸿蒙模拟器效果如下,可以看到轮播图的轮廓已经出来了。接下来我们继续编写其他组件的代码。

2.2 分类组件代码
HmCategory.dart代码
import 'package:flutter/material.dart';
class HmCategory extends StatefulWidget {
const HmCategory({super.key});
@override
State<HmCategory> createState() => _HmCategoryState();
}
class _HmCategoryState extends State<HmCategory> {
@override
Widget build(BuildContext context) {
//返回一个横向滚动的组件,但是得设置高度。但是ListView自身不能设置高度.能设置高度的只有Container和SizeBox
return SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
return Container(
alignment: Alignment.center,
width: 80,
height: 100,
color: Colors.blue,
child: Text("分类$index", style: TextStyle(color: Colors.white)),
margin: EdgeInsets.symmetric(horizontal: 10),
);
}),
);
}
}
完成上述代码后运行到鸿蒙模拟器效果如下,可以看到分类的轮廓已经出来了。

2.3 推荐组件代码
HmSuggestion.dart代码
import 'package:flutter/material.dart';
class HmSuggestion extends StatefulWidget {
const HmSuggestion({super.key});
@override
State<HmSuggestion> createState() => _HmSuggestionState();
}
class _HmSuggestionState extends State<HmSuggestion> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
alignment: Alignment.center,
height: 300,
child: Text(
"推荐",
style: TextStyle(color: Colors.white),
));
}
}
Main/index.dart代码
import 'package:flutter/cupertino.dart';
import 'package:qing_mall/components/Home/HmCategory.dart';
import 'package:qing_mall/components/Home/HmSlider.dart';
import 'package:qing_mall/components/Home/HmSuggestion.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
//获取滚动容器的内容
List<Widget> _getScrollChildren() {
return [
//包裹普通widget的sliver家族的组件内容
SliverToBoxAdapter(child: HmSlider()),//轮播图组件
//放置分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//SliverGrid SliverList指南纵向排列
SliverToBoxAdapter(child: HmCategory()), //分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(child: HmSuggestion()), //推荐组件
SliverToBoxAdapter(child: Flex(
direction: Axis.horizontal,
children: [
],
)),
];
}
@override
Widget build(BuildContext context) {
//CustomScrollview要求:必须是sliver家族的内容
return CustomScrollView(slivers: _getScrollChildren());
}
}

2.4 爆款推荐组件代码
import 'package:flutter/material.dart';
class HmHot extends StatefulWidget {
const HmHot({super.key});
@override
State<HmHot> createState() => _HmHotState();
}
class _HmHotState extends State<HmHot> {
@override
Widget build(BuildContext context) {
return Container(
height: 200,
color: Colors.blue,
alignment: Alignment.center,
child: Text('爆款推荐', style: TextStyle(color: Colors.white)),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:qing_mall/components/Home/HmCategory.dart';
import 'package:qing_mall/components/Home/HmHot.dart';
import 'package:qing_mall/components/Home/HmSlider.dart';
import 'package:qing_mall/components/Home/HmSuggestion.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
//获取滚动容器的内容
List<Widget> _getScrollChildren() {
return [
//包裹普通widget的sliver家族的组件内容
SliverToBoxAdapter(child: HmSlider()),//轮播图组件
//放置分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//SliverGrid SliverList指南纵向排列
SliverToBoxAdapter(child: HmCategory()), //分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(child: HmSuggestion()), //推荐组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//Flex和Expanded配合起来可以均分比例
SliverToBoxAdapter(child: Flex(
direction: Axis.horizontal,
children: [
Expanded(child: HmHot()),
SizedBox(width: 10,),
Expanded(child: HmHot()),
],
)),
];
}
@override
Widget build(BuildContext context) {
//CustomScrollview要求:必须是sliver家族的内容
return CustomScrollView(slivers: _getScrollChildren());
}
}
此时我们发现推荐和爆款间距的部分没有内边距,看起来不太好看,一般电商平台App的这部分都是有间距的,所以我们使用"Padding"组件来完成这个需求。

import 'package:flutter/cupertino.dart';
import 'package:qing_mall/components/Home/HmCategory.dart';
import 'package:qing_mall/components/Home/HmHot.dart';
import 'package:qing_mall/components/Home/HmSlider.dart';
import 'package:qing_mall/components/Home/HmSuggestion.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
//获取滚动容器的内容
List<Widget> _getScrollChildren() {
return [
//包裹普通widget的sliver家族的组件内容
SliverToBoxAdapter(child: HmSlider()), //轮播图组件
//放置分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//SliverGrid SliverList指南纵向排列
SliverToBoxAdapter(child: HmCategory()), //分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(child: HmSuggestion()), //推荐组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//Flex和Expanded配合起来可以均分比例
SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Flex(
direction: Axis.horizontal,
children: [
Expanded(child: HmHot()),
SizedBox(
width: 10,
),
Expanded(child: HmHot()),
],
)),
),
];
}
@override
Widget build(BuildContext context) {
//CustomScrollview要求:必须是sliver家族的内容
return CustomScrollView(slivers: _getScrollChildren());
}
}
import 'package:flutter/material.dart';
class HmSuggestion extends StatefulWidget {
const HmSuggestion({super.key});
@override
State<HmSuggestion> createState() => _HmSuggestionState();
}
class _HmSuggestionState extends State<HmSuggestion> {
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Container(
color: Colors.blue,
alignment: Alignment.center,
height: 300,
child: Text(
"推荐",
style: TextStyle(color: Colors.white),
)));
}
}
加入"Padding 组件"后可以看见,推荐和爆款推荐已经有内边距了

2.5 商品组件代码
HmMoreList.dart代码
import 'package:flutter/material.dart';
class HmMorelist extends StatefulWidget {
const HmMorelist({super.key});
@override
State<HmMorelist> createState() => _HmMorelistState();
}
class _HmMorelistState extends State<HmMorelist> {
@override
Widget build(BuildContext context) {
//必须是Sliver家族的组件
return SliverGrid.builder(gridDelegate:
//网格是两列
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10),
itemBuilder: (BuildContext context, int index) {
return Container(
child: Text("商品", style: TextStyle(color: Colors.white),),
color: Colors.blue,
alignment: Alignment.center,
);
});
}
}
lib/pages/Home/index.dart代码
import 'package:flutter/cupertino.dart';
import 'package:qing_mall/components/Home/HmCategory.dart';
import 'package:qing_mall/components/Home/HmHot.dart';
import 'package:qing_mall/components/Home/HmMoreList.dart';
import 'package:qing_mall/components/Home/HmSlider.dart';
import 'package:qing_mall/components/Home/HmSuggestion.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
//获取滚动容器的内容
List<Widget> _getScrollChildren() {
return [
//包裹普通widget的sliver家族的组件内容
SliverToBoxAdapter(child: HmSlider()), //轮播图组件
//放置分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//SliverGrid SliverList指南纵向排列
SliverToBoxAdapter(child: HmCategory()), //分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(child: HmSuggestion()), //推荐组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//Flex和Expanded配合起来可以均分比例
SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Flex(
direction: Axis.horizontal,
children: [
Expanded(child: HmHot()),
SizedBox(
width: 10,
),
Expanded(child: HmHot()),
],
)),
),
SliverToBoxAdapter(child: SizedBox(height: 10)),
HmMorelist(),//无限滚动列表
];
}
@override
Widget build(BuildContext context) {
//CustomScrollview要求:必须是sliver家族的内容
return CustomScrollView(slivers: _getScrollChildren());
}
}
三、Git上传代码
每次上传代码,基本的步骤基本就是
(1)git add .【提交自己的代码到暂存区】
(2)git commit -m "讲自己干了什么内容" 【讲自己这次干了啥】
(3)git push 【推送到自己的仓库】

如果文章中的代码有问题,大家可以直接看项目的地址,自己克隆源码进行修改,仓库如下:
青商城 - AtomGit
https://AtomGit.com/Deng666/shangcheng
四、结语
通过本文我们完成了组件化的设计。我们将首页拆分为多个独立模块(轮播图、分类、推荐等),每个组件具备独立状态管理能力,使用StatefulWidget实现动态交互。这种架构模式提升了代码复用性和维护效率,符合Flutter声明式UI的开发理念。后续我们将调用API接口渲染到首页的UI上,展示真实的数据。
感谢大家的观看,如果本文章对你有帮助,可以点赞支持一下。如果有疑问,可以在评论区留言,看到会回答。您的点赞将是我最大的动力。
最后
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)