Flutter:导航背景固定在顶部,下拉分页布局


view

js 复制代码
import 'package:ducafe_ui_core/ducafe_ui_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'package:happy/common/index.dart';
import 'index.dart';

class NoticeListPage extends GetView<NoticeListController> {
  const NoticeListPage({super.key});

  // tab 切换
  Widget _buildTab() {
    return <Widget>[
      TextWidget.body('平台公告',size: 30.sp,color: AppTheme.color000,),
      SizedBox(width: 50.w,),
      TextWidget.body('系统消息',size: 30.sp,color: AppTheme.color999,),
    ].toRow()
    .paddingHorizontal(30.w)
    .height(88.w);
  }

  // 数据列表
  Widget _buildDataList() {
    return SmartRefresher(
      controller: controller.refreshController,
      enablePullUp: true,
      onRefresh: controller.onRefresh,
      onLoading: controller.onLoading,
      footer: const SmartRefresherFooterWidget(),
      header: const SmartRefresherHeaderWidget(),
      child: ListView.builder(
        itemBuilder: (context, index) {
          return <Widget>[
            TextWidget.body('happy交易所全新上线啦!',size: 28.sp,color: AppTheme.color000,overflow: TextOverflow.ellipsis,maxLines: 1,),
            SizedBox(height: 20.w,),
            TextWidget.body('交易所全新上线交易所全新上线交易所全新上线交易所全新上线交易所全新上线交易所全新上线交易所全新上线交易所全新上线交易所全新上线',size: 24.sp,color: AppTheme.color999,overflow: TextOverflow.ellipsis,maxLines: 2,),
            SizedBox(height: 30.w,),
            <Widget>[
              TextWidget.body('2020.05.12 12:30',size: 20.sp,color: AppTheme.color999,),
              <Widget>[
                TextWidget.body('查看全部',size: 20.sp,color: AppTheme.color999,),
                Icon(TDIcons.chevron_right,size: 24.sp,color: AppTheme.color999,),
              ].toRow(mainAxisAlignment: MainAxisAlignment.spaceBetween)
            ].toRow(mainAxisAlignment: MainAxisAlignment.spaceBetween)
          ].toColumn(crossAxisAlignment: CrossAxisAlignment.start)
          .paddingAll(30.w)
          .decorated(
            border: Border.all(width: 1,color: AppTheme.dividerColor2),
            color: AppTheme.blockBgColor,
            borderRadius: BorderRadius.circular(10.w)
          )
          .marginOnly(bottom: 20.w,left: 30.w,right: 30.w)
          .onTap(() {
            Get.toNamed('/noticeDetailPage');
          });
        },
        itemCount: 20,
      ),
    );
  }

  // 主视图
  Widget _buildView() {
    // 系统状态栏占位高度
    double systemStatusBarHeight = MediaQuery.of(Get.context!).padding.top;
    // 总占位高度
    double systemTotalHeight = 44 + systemStatusBarHeight;
    return <Widget>[
      SizedBox(height: systemTotalHeight,),
      _buildTab(),
      _buildDataList().expanded(),
    ].toColumn();
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<NoticeListController>(
      init: NoticeListController(),
      id: "notice_list",
      builder: (_) {
        return Scaffold(
          backgroundColor: AppTheme.pageBgColor, // 自定义颜色
          body: <Widget>[
            ImgWidget(path: 'assets/images/home10.png',width: 750.w,height: 500.w,),
            _buildView().expanded(),
            TDNavBar(
              height: 44,
              title: '消息详情',
              titleColor: AppTheme.color000,
              titleFontWeight: FontWeight.w600,
              backgroundColor: Colors.transparent,
              screenAdaptation: true,
              useDefaultBack: false,
              leftBarItems: [
                TDNavBarItem(
                  icon: TDIcons.chevron_left,
                  iconSize: 24,
                  iconColor: AppTheme.color000,
                  action: () {
                    Get.back();
                  }
                ),
              ],
            ),
          ].toStack(),
        );
      },
    );
  }
}

controller

js 复制代码
import 'package:get/get.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
// import 'package:happy/common/index.dart';

class NoticeListController extends GetxController {
  NoticeListController();

  // 查看详情
  void goNoticeDetail(String id) {
    Get.toNamed('/noticeDetailPage',arguments: {'id': id});
  }

  List items = [];

  /*
  * 分页
  * refreshController:分页控制器
  * _page:分页
  * _limit:每页条数
  * _loadNewsSell:拉取数据(是否刷新)
  * onLoading:上拉加载新商品
  * onRefresh:下拉刷新
  * */
  final RefreshController refreshController = RefreshController(
    initialRefresh: true,
  );
  // int _page = 1;
  Future<bool> _loadNewsSell(bool isRefresh) async {
    return false;
    // var result = await HomeApi.noticesList(PageListReq(
    //   pageNo:isRefresh ? 1:_page,
    //   pageSize:20
    // ));
    // if(isRefresh){
    //   _page = 1;
    //   items.clear();
    // }
    // if(result.isNotEmpty){
    //   _page++;
    //   items.addAll(result);
    // }
    // // 是否是空
    // return result.isEmpty;
  }

  // 上拉载入新商品
  void onLoading() async {
    if (items.isNotEmpty) {
      try {
        // 拉取数据是否为空 ? 设置暂无数据 : 加载完成
        var isEmpty = await _loadNewsSell(false);
        isEmpty
            ? refreshController.loadNoData()
            : refreshController.loadComplete();
      } catch (e) {
        refreshController.loadFailed(); // 加载失败
      }
    } else {
      refreshController.loadNoData(); // 设置无数据
    }
    update(["goods_list"]);
  }

  // 下拉刷新
  void onRefresh() async {
    try {
      await _loadNewsSell(true);
      refreshController.refreshCompleted();
    } catch (e) {
      refreshController.refreshFailed();
    }
    update(["notice_list"]);
  }



  _initData() {
    update(["notice_list"]);
  }


  @override
  void onReady() {
    super.onReady();
    _initData();
  }

  @override
  void onClose() {
    super.onClose();
    refreshController.dispose();
  }
}
相关推荐
半个落月4 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
半个落月4 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
小 黄 鸡5 小时前
Flutter 面试必会知识点详解(从基础到进阶)
flutter·面试·职场和发展
程序猿追5 小时前
kotlin-retry 接入鸿蒙后,怎样确认它真的会停止重试
开发语言·kotlin·harmonyos
我是人✓5 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
智能直播5 小时前
网络RTMP拉流不卡顿、声音不同步,一文讲透缓冲区、时间戳
开发语言·ffmpeg·php·音视频·视频编解码
墨云安全6 小时前
内网资产无法暴露到公网,怎么做安全检测?2026 年内网渗透测试的落地路径
开发语言·安全·网络安全·渗透测试·php
u0111026756 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
摇滚侠6 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记
Cc.Y6 小时前
Java零基础入门:深入Java核心:文件IO与序列化全解
java·开发语言·python