Flutter顶部TabBar和表格TableRow

Flutter顶部TabBar和表格TableRow

需求:

显示样式为这样

截屏2022-01-14 下午5.24.01

1、可左右滑动切换表格

2、网络请求:一、切换才请求页面,二、表格有页码,支持上下拉刷新加载更多

3、表格做缓存处理(用户滑到哪里,切换表格再切回来还是那个位置)

4、点击行触发事件跳转

5、跳转后下一个页面影响到该页面的数据(重新更新数据)

UI代码分析

TabBar

如果单独写TabBar的话,会直接占满整个屏幕的宽度,所以外面需要套一层Container控制它的宽高。

TabBar的controller为

_tabController = TabController(length: titleModel.length, vsync: this);

// 标题
  void setTitleModel() {
   
    titleModel = [];
    titleModel.add('第一个表格名称');
    titleModel.add('第二个表格名称');
  }

如果有需要监听滑动切换的需求,我也用不着,所以这个可以删掉

_tabController.addListener(() {
   
      print(_tabController.index);
    });

整体结构为 行(TabBar + TabBarView),未选中样式和选中样式都可以更改

Widget _successWidget() {
   
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(padding: const EdgeInsets.fromLTRB(15, 10, 0, 0),child: Container(
          width: 192,
          height: 30,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(4),
            border: Border.all(width: 1, color: AppColor.themeBlue),
          ),
          child: TabBar(
              controller: _tabController,

              //未选中样式
              unselectedLabelColor: AppColor.themeBlue,
              unselectedLabelStyle: const TextStyle(
                  fontWeight: FontWeight.normal,
                  fontSize: 15,
                  color: Colors.white),
              indicator: const BoxDecoration(
                color: AppColor.themeBlue,
              )
要使用 IntelliJ IDEA(或 Android Studio)的 Flutter 插件完成实验室安全测试平台的应用程序开发,你可以参考以下步骤: ### 1. 准备工作 #### 添加依赖 在 `pubspec.yaml` 文件中添加必要的依赖,例如 `sqflite` 用于数据库操作。 ```yaml dependencies: flutter: sdk: flutter sqflite: ^1.3.0 ``` 保存文件后,点击编辑窗口右上角的 "Packages get" 按钮安装依赖。 ### 2. 数据库设计 #### 创建数据库文件 根据需求,创建包含 8 个表的 `school.db` 数据库文件,每个表对应一种题库类。表结构如下: ```sql CREATE TABLE tsl ( tino INTEGER PRIMARY KEY, ticontent TEXT, tia TEXT, tib TEXT, tic TEXT, tid TEXT, tianswer TEXT, titype INTEGER ); -- 其他表类似,例如 hxl, yxswl, jxjzl, dql, fsl, tzsbl, xfl ``` #### 将数据库文件放入资源目录 将 `school.db` 放入项目的 `assets/db` 目录,并在 `pubspec.yaml` 文件中声明资源文件。 ```yaml flutter: assets: - assets/db/school.db ``` ### 3. 初始化数据库 #### 定义初始化数据库方法 在应用启动时检查数据库文件是否存在,如果不存在则从资源文件中复制。 ```dart import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart'; import 'dart:io'; import 'package:path/path.dart'; Future<Database> initDB() async { String path = join(await getDatabasesPath(), 'school.db'); bool exists = await databaseExists(path); if (!exists) { try { await Directory(dirname(path)).create(recursive: true); } catch (_) {} ByteData data = await rootBundle.load(join('assets', 'db', 'school.db')); List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); await File(path).writeAsBytes(bytes, flush: true); } return await openDatabase(path); } ``` ### 4. 题库选择页面 #### 定义题库类别按钮组 创建题库选择页面,包含题库类别的按钮组。 ```dart import 'package:flutter/material.dart'; class MainPage extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MainPageState(), ); } } class MainPageState extends StatefulWidget { @override _MainPageState createState() => _MainPageState(); } class _MainPageState extends State<MainPageState> { List<String> types = [ '通识类\n安全题', '化学类\n安全题', '医学生物类\n安全题', '机械建筑类\n安全题', '电气类\n安全题', '辐射类\n安全题', '特种设备\n安全题', '消防\n安全题', '退出系统' ]; List<Widget> selects = []; @override void initState() { super.initState(); initFlatButton(types, context); } void initFlatButton(List<String> types, BuildContext context) { for (int i = 0; i < types.length; i++) { FlatButton flatButton = FlatButton( color: Colors.blue, child: Text( types[i], style: TextStyle(fontSize: 18), textAlign: TextAlign.center, ), onPressed: () { if (i < types.length - 1) { Navigator.push( context, MaterialPageRoute( builder: (context) => Exam(examId: i, db: initDB()), ), ); } else { exit(0); } }, ); selects.add(flatButton); } } @override Widget build(BuildContext context) { GridView gridView = GridView.count( crossAxisCount: 3, mainAxisSpacing: 3, crossAxisSpacing: 3, children: selects, ); return Scaffold( appBar: AppBar(title: Text('实验室安全测试平台')), body: Padding( padding: EdgeInsets.all(10), child: gridView, ), ); } } ``` ### 5. 测试页面 #### 获取测试题库表 根据用户选择的题库类型,从数据库中读取相应的题目。 ```dart import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; class Exam extends StatefulWidget { final int examId; final Future<Database> db; Exam({@required this.examId, @required this.db}); @override _ExamState createState() => _ExamState(); } class _ExamState extends State<Exam> { int examNo; Database studyDB; List<Map<String, dynamic>> maps = []; List<Map<String, dynamic>> smaps = []; String examType = 'tsl'; int jindex = 0; var jselected = ''; String jticontent = ''; String jtino = ''; String jtia = ''; String jtib = ''; String jtianswer = ''; @override void initState() { super.initState(); widget.db.then((value) { studyDB = value; examNo = widget.examId; examType = getExamType(examNo); getJudgeDetail(examType, '1'); getSingleDetail(examType, '2'); }); } String getExamType(int examNo) { switch (examNo) { case 0: return 'tsl'; case 1: return 'hxl'; case 2: return 'yxswl'; case 3: return 'jxjzl'; case 4: return 'dql'; case 5: return 'fsl'; case 6: return 'tzsbl'; case 7: return 'xfl'; default: return 'tsl'; } } void getJudgeDetail(String examType, String tiType) async { List<dynamic> values = [tiType]; String sql = 'SELECT * FROM $examType WHERE titype = ?'; List<Map<String, dynamic>> maps = await studyDB.rawQuery(sql, values); setState(() { this.maps = maps; if (maps.isNotEmpty) { jtino = maps[0]['tino'].toString(); jticontent = maps[0]['ticontent']; jtia = maps[0]['tia']; jtib = maps[0]['tib']; jtianswer = maps[0]['tianswer']; } }); } void getSingleDetail(String examType, String tiType) async { List<dynamic> values = [tiType]; String sql = 'SELECT * FROM $examType WHERE titype = ?'; List<Map<String, dynamic>> smaps = await studyDB.rawQuery(sql, values); setState(() { this.smaps = smaps; }); } @override Widget build(BuildContext context) { // 生成测试页面 Widget jdetail = Padding( padding: EdgeInsets.all(8), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text('$jtino, $jticontent'), RadioListTile( value: 'a', groupValue: jselected, title: Text('A'), subtitle: Text(jtia), onChanged: (value) { setState(() { jselected = value; }); }, ), // 其他选项代码类似 Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[ Text( '你选的答案为:$jselected', style: TextStyle(color: jselected == jtianswer ? Colors.black : Colors.red), ), FlatButton( child: Text('查看解析'), onPressed: () { showModalBottomSheet( context: context, builder: (context) { return Container( alignment: Alignment.center, height: 100, child: Text('标准答案为:$jtianswer'), ); }, ); }, ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[ RaisedButton( child: Text('上一题'), onPressed: () { if (jindex > 0) { jindex--; setState(() { jselected = ''; jtino = maps[jindex]['tino'].toString(); jticontent = maps[jindex]['ticontent']; jtia = maps[jindex]['tia']; jtib = maps[jindex]['tib']; jtianswer = maps[jindex]['tianswer']; }); } }, ), RaisedButton( child: Text('下一题'), onPressed: () { if (jindex < maps.length - 1) { jindex++; setState(() { jselected = ''; jtino = maps[jindex]['tino'].toString(); jticontent = maps[jindex]['ticontent']; jtia = maps[jindex]['tia']; jtib = maps[jindex]['tib']; jtianswer = maps[jindex]['tianswer']; }); } }, ), ], ), ], ), ); // 选择题测试页面 (sdetail) 代码类似 TabBar tabBar = TabBar( tabs: <Widget>[ Tab(icon: Icon(Icons.offline_pin), text: '判断题'), Tab(icon: Icon(Icons.panorama_fish_eye), text: '选择题'), ], labelColor: Colors.yellow, ); TabBarView tabBarView = TabBarView( children: <Widget>[ jdetail, // sdetail, ], ); DefaultTabController tabController = DefaultTabController( length: 2, child: Scaffold( appBar: AppBar( title: Text(getExamType(examNo)), bottom: tabBar, ), body: tabBarView, ), ); return tabController; } } ``` ### 6. 运行应用 在 IntelliJ IDEA 或 Android Studio 中运行应用,确保所有配置正确无误。 通过以上步骤,你可以完成实验室安全测试平台的应用程序开发。希望这对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值