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

Flutter实现背景组件上方的滚动视图(仿谷歌天气App)

实现谷歌天气式滚动背景效果

要实现你需要的效果,核心是动态控制滚动视图的初始偏移量,让内容默认处于屏幕外,同时适配不同屏幕尺寸。以下是可行的实现方案:

解决方案思路

  • 用Stack维持Lottie背景与滚动内容的层级,背景铺满整个视口。
  • 通过ScrollController设置初始滚动偏移,让内容默认位于屏幕底部之外,用户滚动时才逐步进入视野。
  • 借助MediaQuery或LayoutBuilder获取屏幕/容器尺寸,动态计算初始偏移量,替代固定高度的SizedBox解决适配问题。

完整代码实现

import 'package:lottie/lottie.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late ScrollController _scrollController;
  double _initialScrollOffset = 0;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    // 布局完成后再计算偏移,确保尺寸准确
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (mounted) {
        setState(() {
          final screenHeight = MediaQuery.of(context).size.height;
          // 估算顶部文本区域高度,也可用GlobalKey获取精确值
          final topAreaHeight = 40;
          // 计算初始偏移:让列表内容刚好处于屏幕底部外
          _initialScrollOffset = screenHeight - topAreaHeight - 32;
          _scrollController.jumpTo(_initialScrollOffset);
        });
      }
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Stack(
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(12),
              child: Lottie.asset(
                'assets/landscape.zip',
                fit: BoxFit.cover,
                height: double.infinity,
                width: double.infinity,
              ),
            ),
            CustomScrollView(
              controller: _scrollController,
              slivers: [
                SliverToBoxAdapter(
                  child: const Padding(
                    padding: EdgeInsets.all(8.0),
                    child: Text(
                      "Good Morning!",
                      style: TextStyle(fontWeight: FontWeight.bold),
                    ),
                  ),
                ),
                SliverPadding(
                  padding: const EdgeInsets.all(8.0),
                  sliver: SliverList(
                    delegate: SliverChildListDelegate(
                      [
                        Container(
                          color: Colors.grey[300],
                          height: 200,
                          margin: const EdgeInsets.only(bottom: 10),
                        ),
                        Container(
                          color: Colors.grey[300],
                          height: 200,
                        ),
                        Container(
                          color: Colors.grey[300],
                          height: 200,
                          margin: const EdgeInsets.only(top: 10),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

关键细节说明

  1. 动态偏移计算:通过MediaQuery获取屏幕高度,结合顶部文本区域的高度,算出刚好让列表内容处于屏幕外的初始滚动偏移,彻底解决固定高度的适配问题。
  2. 延迟执行逻辑:用WidgetsBinding.instance.addPostFrameCallback确保在布局渲染完成后再计算偏移,避免获取到错误的尺寸值。
  3. 精确尺寸获取(可选):如果需要更精准的顶部区域高度,可以给文本组件添加GlobalKey,通过key.currentContext?.size?.height获取实际渲染高度,替换代码中估算的topAreaHeight。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:15:42