You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

参考React Native案例,如何在Flutter中实现Bottom Sheet背景缩放效果?

Flutter实现Bottom Sheet背景缩放效果

要实现类似React Native中Bottom Sheet展开时背景缩放的效果,我们可以利用Flutter的DraggableScrollableSheet组件结合Transform.scale动态控制背景元素的缩放,核心逻辑是监听底部弹窗的拖拽进度,实时调整背景的缩放比例。

实现代码示例

import 'package:flutter/material.dart';

class BackgroundZoomBottomSheet extends StatefulWidget {
  const BackgroundZoomBottomSheet({super.key});

  @override
  State<BackgroundZoomBottomSheet> createState() => _BackgroundZoomBottomSheetState();
}

class _BackgroundZoomBottomSheetState extends State<BackgroundZoomBottomSheet> {
  // 弹窗收起时背景处于放大状态,初始缩放值设为1.2
  double _backgroundScale = 1.2;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // 可动态缩放的背景层
          Transform.scale(
            scale: _backgroundScale,
            alignment: Alignment.center,
            child: Image.network(
              'https://picsum.photos/1080/1920',
              fit: BoxFit.cover,
              height: double.infinity,
              width: double.infinity,
            ),
          ),
          // 监听弹窗拖拽进度,更新背景缩放
          NotificationListener<DraggableScrollableNotification>(
            onNotification: (notification) {
              // 将弹窗的extent范围转换为0-1的拖拽进度比例
              final progress = (notification.extent - notification.minExtent) / 
                               (notification.maxExtent - notification.minExtent);
              // 随弹窗展开,背景从1.2逐步缩小到1
              setState(() {
                _backgroundScale = 1.2 - (progress * 0.2);
              });
              return true;
            },
            child: DraggableScrollableSheet(
              initialChildSize: 0.3, // 弹窗初始高度占可用空间30%
              minChildSize: 0.3,     // 弹窗最小高度占比
              maxChildSize: 0.9,     // 弹窗最大高度占比
              builder: (context, scrollController) {
                return Container(
                  decoration: const BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
                  ),
                  child: ListView.builder(
                    controller: scrollController,
                    itemCount: 20,
                    itemBuilder: (context, index) => ListTile(title: Text('列表项 $index')),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

关键细节说明

  • 层级结构:通过Stack将背景图和底部弹窗叠加,确保背景图处于底层,缩放时不会遮挡弹窗。
  • 缩放逻辑:使用Transform.scale组件动态修改scale值,结合setState触发UI更新。
  • 进度映射:借助DraggableScrollableNotification获取弹窗的拖拽进度,将其转换为0-1的比例后,映射到背景缩放值的变化区间。
  • 自定义调整:
    • 若需要背景随弹窗展开而放大,可将缩放公式改为_backgroundScale = 1 + (progress * 0.2),初始值设为1。
    • 修改initialChildSize、minChildSize、maxChildSize可调整弹窗的初始高度和拖拽范围。
    • 调整_backgroundScale的初始值和变化幅度,能改变背景缩放的视觉强度。

内容的提问来源于stack exchange,提问作者Riri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 10:05:06