Flutter:页面滚动,导航栏背景颜色过渡动画

记录:导航默认透明,页面发生滚动后,导航背景色由0-1,过渡到白色背景。



view

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

class SendRedPacketReceivePage extends GetView<SendRedPacketReceiveController> {
  const SendRedPacketReceivePage({super.key});

  // 头部
  Widget _buildHeader() {
    return <Widget>[
      TDImage(assetUrl: 'assets/chat/images/6.png', width: 750.w, height: 216.w,type: TDImageType.square,),
      <Widget>[
        SizedBox(height: 150.w,),
        TDImage(assetUrl: 'assets/chat/images/user.png', width: 130.w, height: 130.w,type: TDImageType.circle,),
        SizedBox(height: 20.w,),
        TextWidget.body('黄玲玲发出的红包', size: 32.sp, color: AppTheme.color333,weight: FontWeight.w600,),
        SizedBox(height: 10.w,),
        TextWidget.body('恭喜发财,大吉大利', size: 26.sp, color: AppTheme.color999,),
        SizedBox(height: 10.w,),
        <Widget>[
          TextWidget.body('8.88', size: 80.sp, color: AppTheme.primary,weight: FontWeight.w600,),
          SizedBox(width: 10.w,),
          TextWidget.body('元', size: 26.sp, color: AppTheme.primary,weight: FontWeight.w600,),
        ].toRow(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.baseline,textBaseline: TextBaseline.alphabetic),
      ].toColumn()
    ].toStack();
  }

  // 红包总数
  Widget _buildRedPacketCount() {
    return <Widget>[
      TextWidget.body('共10个红包,5秒钟抢完', size: 26.sp, color: AppTheme.color999,),
    ].toRow()
    .paddingHorizontal(30.w)
    .height(68.w).backgroundColor(const Color(0xfff3f4f5))
    .clipRRect(all: 10.w);
  }

  // 红包列表
  Widget _buildRedPacketList() {
    return SliverList(
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return <Widget>[
            TDImage(assetUrl: 'assets/chat/images/user.png',width: 84.w,height: 84.w, type: TDImageType.circle,),
            SizedBox(width: 20.w),
            <Widget>[
              TextWidget.body('黄玲玲', size: 30.sp,color: AppTheme.color333,),
              SizedBox(height: 10.w),
              TextWidget.body('2024-01-01 12:00',size: 24.sp,color: AppTheme.color999,),
            ].toColumn(crossAxisAlignment: CrossAxisAlignment.start,)
            .expanded(),
            TextWidget.body('0.88元',size: 30.sp,color: AppTheme.color333,),
          ].toRow(crossAxisAlignment: CrossAxisAlignment.start)
          .paddingVertical(20.w)
          .decorated(border: const Border(bottom: BorderSide(width: 1, color: AppTheme.dividerColor),));
        },
        childCount: 15,
      ),
    );
  }

  // 主视图
  Widget _buildView() {
    return CustomScrollView(
      controller: controller.scrollController,
      slivers: [
        _buildHeader().sliverToBoxAdapter(),
        SizedBox(height: 60.w,).sliverToBoxAdapter(),
        _buildRedPacketCount().sliverToBoxAdapter().sliverPaddingHorizontal(30.w),
        SizedBox(height: 20.w,).sliverToBoxAdapter(),
        _buildRedPacketList().sliverPaddingHorizontal(30.w),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<SendRedPacketReceiveController>(
      init: SendRedPacketReceiveController(),
      id: "send_red_packet_receive",
      builder: (_) {
        return Scaffold(
          backgroundColor: AppTheme.pageBgColor,
          body: <Widget>[
            _buildView(),
            AnimatedContainer(
              duration: const Duration(milliseconds: 100),
              color: Colors.white.withOpacity(controller.opacity),
              child: TDNavBar(
                height: 44,
                title: '领取红包',
                titleColor: AppTheme.color333.withOpacity(controller.opacity),
                titleFontWeight: FontWeight.w600,
                backgroundColor: Colors.transparent,
                screenAdaptation: true,
                useDefaultBack: true,
              ),
            ).positioned(left: 0, right: 0, top: 0),
          ].toStack()
        );
      },
    );
  }
}

controller

js 复制代码
import 'package:get/get.dart';
import 'package:flutter/material.dart';

class SendRedPacketReceiveController extends GetxController {
  SendRedPacketReceiveController();

  // 滚动控制器
  final ScrollController scrollController = ScrollController();
  
  // 渐变系数 0-1
  double opacity = 0.0;
  
  // 滚动开始变化的位置
  final double scrollStartPoint = 20.0;
  
  // 滚动结束变化的位置
  final double scrollEndPoint = 120.0;

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


  @override
  void onInit() {
    super.onInit();
    // 监听滚动
    scrollController.addListener(() {
      // 计算 0-1 之间的渐变系数
      double newOpacity;
      
      if (scrollController.offset <= scrollStartPoint) {
        // 开始点之前完全透明
        newOpacity = 0.0;
      } else if (scrollController.offset >= scrollEndPoint) {
        // 结束点之后完全不透明
        newOpacity = 1.0;
      } else {
        // 在开始点和结束点之间线性计算
        newOpacity = (scrollController.offset - scrollStartPoint) /  (scrollEndPoint - scrollStartPoint);
        
        // 确保值在0-1范围内并保留更多小数位精度
        newOpacity = double.parse(newOpacity.toStringAsFixed(3)).clamp(0.0, 1.0);
      }
      
      // 只有当透明度变化时才更新UI
      if ((opacity - newOpacity).abs() > 0.001) {
        opacity = newOpacity;
        update(["send_red_packet_receive"]);
      }
    });
    _initData();
  }

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

  @override
  void onClose() {
    scrollController.dispose();
    super.onClose();
  }
}
相关推荐
dialect_5 小时前
KMP算法
开发语言·c++·算法
jktantan6 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
总要学点什么6 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
前端精髓7 小时前
调用openrouter的免费API模型
java·前端·javascript
开开心心_Every8 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
chenbingjie_c8 小时前
C++ 多态完全指南:从虚函数重写到虚函数表原理
开发语言·c++
吴卫斌8 小时前
定投ETF实战指南(四):行业/主题ETF——定投的“进攻端“
开发语言·python·股票·量化
超级架构师9 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
叼烟扛炮10 小时前
Linux 学习笔记(四十三):网络编程进阶——自定义协议解决 TCP 粘包与守护进程
linux·开发语言·网络·笔记·tcp/ip
LMT流氓兔10 小时前
第五单元——第十六课:给书店助手加上网页界面
java·开发语言·jvm·人工智能·oracle·langchain·1024程序员节