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();
  }
}
相关推荐
ShallowLin几秒前
vue3学习——组合式 API:生命周期钩子
前端·javascript·vue.js
Nejosi_念旧21 分钟前
Vue API 、element-plus自动导入插件
前端·javascript·vue.js
麻芝汤圆1 小时前
MapReduce 入门实战:WordCount 程序
大数据·前端·javascript·ajax·spark·mapreduce
巨龙之路2 小时前
C语言中的assert
c语言·开发语言
2301_776681653 小时前
【用「概率思维」重新理解生活】
开发语言·人工智能·自然语言处理
熊大如如3 小时前
Java 反射
java·开发语言
Peter 谭4 小时前
React Hooks 实现原理深度解析:从基础到源码级理解
前端·javascript·react.js·前端框架·ecmascript
ll7788114 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
我不想当小卡拉米4 小时前
【Linux】操作系统入门:冯诺依曼体系结构
linux·开发语言·网络·c++
周胡杰4 小时前
鸿蒙接入flutter环境变量配置windows-命令行或者手动配置-到项目的创建-运行demo项目
javascript·windows·flutter·华为·harmonyos·鸿蒙·鸿蒙系统