news 2026/5/14 9:27:06

【Flutter for OpenHarmony】实战 - Day 2(2):课表页面完善

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Flutter for OpenHarmony】实战 - Day 2(2):课表页面完善

从零搭建课表列表视图,实现日期选择与课程卡片展示
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

一、本日目标

  1. 实现课表列表视图
  2. 添加日期选择器组件
  3. 创建课程卡片组件
  4. 整合静态课程数据

二、文件结构

lib/ ├── data/ │ └── mock_course_data.dart # 静态课程数据 ├── models/ │ └── course.dart # 课程数据模型 ├── widgets/ │ ├── course_card.dart # 课程卡片组件 │ └── date_selector.dart # 日期选择器组件 └── pages/ └── home_page.dart # 课表主页(含列表视图)

三、核心代码实现

3.1 课程数据模型 (lib/models/course.dart)
classCourse{finalStringid;finalStringname;// 课程名称finalStringteacher;// 授课教师finalStringlocation;// 上课地点finalint weekday;// 周几 (1-7,周一为1)finalint startWeek;// 起始周finalint endWeek;// 结束周finalint startSection;// 开始节次finalint endSection;// 结束节次finalStringcolorHex;// 课程颜色Course({requiredthis.id,requiredthis.name,requiredthis.teacher,requiredthis.location,requiredthis.weekday,requiredthis.startWeek,requiredthis.endWeek,requiredthis.startSection,requiredthis.endSection,requiredthis.colorHex,});}
3.2 静态课程数据 (lib/data/mock_course_data.dart)

后续可改为动态数据,通过读取图片或用户手动的方式输入

import'../models/course.dart';classMockCourseData{staticfinalList<Course>courses=[Course(id:'1',name:'高等数学',teacher:'张教授',location:'教学楼A101',weekday:1,startWeek:1,endWeek:16,startSection:1,endSection:2,colorHex:'#4A6FA5',),Course(id:'2',name:'大学英语',teacher:'李老师',location:'教学楼B202',weekday:1,startWeek:1,endWeek:16,startSection:3,endSection:4,colorHex:'#67B7DC',),Course(id:'3',name:'程序设计',teacher:'王教授',location:'实验楼C301',weekday:2,startWeek:1,endWeek:16,startSection:1,endSection:3,colorHex:'#FF9800',),// ... 周一至周五均有课程数据];}
3.3 课程卡片组件 (lib/widgets/course_card.dart)
classCourseCardextendsStatelessWidget{finalCoursecourse;constCourseCard({super.key,requiredthis.course});@overrideWidgetbuild(BuildContextcontext){returnContainer(margin:constEdgeInsets.only(bottom:12),decoration:BoxDecoration(color:Colors.white,borderRadius:BorderRadius.circular(12),boxShadow:[BoxShadow(color:Colors.grey.withOpacity(0.1),blurRadius:8)],),child:Material(borderRadius:BorderRadius.circular(12),child:InkWell(onTap:(){},// 后续实现课程详情child:Container(padding:constEdgeInsets.all(12),decoration:BoxDecoration(borderRadius:BorderRadius.circular(12),border:Border(left:BorderSide(color:Color(int.parse(course.colorHex.replaceFirst('#','0xFF'))),width:4,),),),child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Text(course.name,style:constTextStyle(fontSize:16,fontWeight:FontWeight.bold)),constSizedBox(height:4),Row(children:[Icon(Icons.person_outline,size:14,color:Colors.grey[600]),constSizedBox(width:4),Text(course.teacher,style:TextStyle(fontSize:13,color:Colors.grey[700])),constSizedBox(width:12),Icon(Icons.room_outlined,size:14,color:Colors.grey[600]),constSizedBox(width:4),Text(course.location,style:TextStyle(fontSize:13,color:Colors.grey[700])),],),constSizedBox(height:4),Text('第${course.startWeek}-${course.endWeek}周 第${course.startSection}-${course.endSection}节',style:TextStyle(fontSize:12,color:Colors.grey[500])),],),),),),);}}
3.4 日期选择器组件 (lib/widgets/date_selector.dart)
classDateSelectorextendsStatelessWidget{finalint selectedWeekday;finalFunction(int)onWeekdaySelected;constDateSelector({super.key,requiredthis.selectedWeekday,requiredthis.onWeekdaySelected,});@overrideWidgetbuild(BuildContextcontext){finalweekdays=['一','二','三','四','五','六','日'];returnContainer(padding:constEdgeInsets.symmetric(vertical:12),child:Row(mainAxisAlignment:MainAxisAlignment.spaceEvenly,children:List.generate(7,(index){finalweekday=index+1;finalisSelected=selectedWeekday==weekday;returnGestureDetector(onTap:()=>onWeekdaySelected(weekday),child:Container(width:42,height:42,decoration:BoxDecoration(shape:BoxShape.circle,color:isSelected?Colors.blue:Colors.transparent,),child:Center(child:Text(weekdays[index],style:TextStyle(fontSize:18,fontWeight:isSelected?FontWeight.bold:FontWeight.normal,color:isSelected?Colors.white:Colors.grey[800],),),),),);}),),);}}
3.5 课表主页 (lib/pages/home_page.dart)
classHomePageextendsStatefulWidget{constHomePage({super.key});@overrideState<HomePage>createState()=>_HomePageState();}class_HomePageStateextendsState<HomePage>{int _currentIndex=0;@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text(['课表','作业','我的'][_currentIndex])),body:_buildBody(),bottomNavigationBar:BottomNavigationBar(currentIndex:_currentIndex,onTap:(index)=>setState(()=>_currentIndex=index),items:const[BottomNavigationBarItem(icon:Icon(Icons.calendar_today),label:'课表'),BottomNavigationBarItem(icon:Icon(Icons.assignment),label:'作业'),BottomNavigationBarItem(icon:Icon(Icons.person),label:'我的'),],),);}Widget_buildBody(){switch(_currentIndex){case0:returnconst_CourseContent();case1:returnconstHomeworkPage();case2:returnconstProfilePage();default:returnconst_CourseContent();}}}// 课表列表视图组件class_CourseContentextendsStatefulWidget{const_CourseContent();@overrideState<_CourseContent>createState()=>_CourseContentState();}class_CourseContentStateextendsState<_CourseContent>{int _selectedWeekday=DateTime.now().weekday;@overrideWidgetbuild(BuildContextcontext){finalfilteredCourses=MockCourseData.courses.where((course)=>course.weekday==_selectedWeekday).toList();returnColumn(children:[DateSelector(selectedWeekday:_selectedWeekday,onWeekdaySelected:(weekday)=>setState(()=>_selectedWeekday=weekday),),Expanded(child:filteredCourses.isEmpty?constCenter(child:Column(mainAxisAlignment:MainAxisAlignment.center,children:[Icon(Icons.free_breakfast,size:64,color:Colors.grey),Text('今天没有课程安排')],)):ListView.builder(padding:constEdgeInsets.all(16),itemCount:filteredCourses.length,itemBuilder:(context,index)=>CourseCard(course:filteredCourses[index]),),),],);}}

四、本日成果

成果说明
✅ 课程数据模型定义 Course 类,包含课程名称、教师、地点、节次等字段
✅ 静态课程数据mock_course_data.dart 包含周一至周五课程
✅ 课程卡片组件展示课程详情,左侧彩色边框
❗ 日期选择器横向滚动星期选择,选中高亮
✅ 课表列表视图按选中日期筛选并展示课程卡片

五、运行验证

flutter run
预期效果状态
顶部显示星期选择器
默认选中当前星期
点击日期切换课程列表
课程卡片完整展示信息
无课日期显示提示

六、下一步计划

任务优先级
优化日期选择,增加星期切换
添加课程功能(弹窗表单)
编辑/删除课程
本地存储(shared_preferences)
课程详情页
作业管理页面

本日完成:课表列表视图完整实现,支持日期切换和课程卡片展示。下一步将实现添加课程功能。剩下的明天再说,好困。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 9:21:27

零成本自建AI代理搜索引擎:基于SearXNG与Redis缓存的实战方案

1. 项目概述&#xff1a;零成本自建AI代理搜索引擎如果你正在开发一个需要联网搜索功能的AI应用&#xff0c;比如智能客服、研究助手或者一个能自动获取最新信息的聊天机器人&#xff0c;那么你一定对搜索API的成本感到头疼。市面上的主流方案&#xff0c;无论是Brave、Tavily还…

作者头像 李华
网站建设 2026/5/14 9:15:05

Python开发者如何构建个人技能库:从代码片段到高效编程

1. 项目概述&#xff1a;一个Python开发者的“兵器库”在Python开发这条路上摸爬滚打久了&#xff0c;你会发现一个有趣的现象&#xff1a;高手和新手之间的差距&#xff0c;往往不在于对某个框架的掌握深度&#xff0c;而在于对“工具”和“技巧”的运用效率。这里的“工具”不…

作者头像 李华
网站建设 2026/5/14 9:14:30

【生成模型】DDPM扩散模型:从数学原理到PyTorch实战

1. 扩散模型的前世今生 我第一次接触DDPM是在2021年做图像生成项目时&#xff0c;当时被它"先破坏再重建"的思路惊艳到了。想象一下&#xff0c;你有一幅名画&#xff0c;每天往上面撒一点盐&#xff0c;直到完全看不清原貌——这就是前向扩散过程。神奇的是&#xf…

作者头像 李华