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

使用Flutter实现Telegram风格的AppBar

实现Telegram风格滚动收缩AppBar

当然可以实现这个效果,用Flutter原生组件就能搞定,不用依赖第三方库。下面是具体实现方案:

核心思路

借助SliverAppBar的滚动收缩特性,在其flexibleSpace区域自定义布局,根据滚动时AppBar的高度变化,动态调整头像、标题的大小、位置,模拟Telegram的平滑收缩效果。

完整代码示例

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Telegram Style AppBar',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final statusBarHeight = MediaQuery.of(context).padding.top;
    const expandedHeight = 200.0;
    const minAppBarHeight = kToolbarHeight;

    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            pinned: true,
            expandedHeight: expandedHeight,
            backgroundColor: Colors.blue,
            flexibleSpace: LayoutBuilder(
              builder: (context, constraints) {
                // 计算收缩比例:0=完全展开,1=完全收缩
                final scrollPercentage = (expandedHeight - constraints.maxHeight) /
                    (expandedHeight - minAppBarHeight);
                final clampedPercentage = scrollPercentage.clamp(0.0, 1.0);

                // 头像尺寸:从60收缩到40
                final avatarSize = 60 - (20 * clampedPercentage);
                // 标题字号:从24收缩到18
                final titleFontSize = 24 - (6 * clampedPercentage);
                // 标题垂直位置:随收缩比例上移
                final titleTopOffset = statusBarHeight + 
                    (expandedHeight - minAppBarHeight) * (1 - clampedPercentage) / 2;

                return Stack(
                  children: [
                    Container(color: Colors.blue),
                    // 头像
                    Positioned(
                      left: 16,
                      top: statusBarHeight + 
                          (expandedHeight - avatarSize) / 2 * (1 - clampedPercentage) + 
                          (minAppBarHeight - avatarSize) / 2 * clampedPercentage,
                      child: CircleAvatar(
                        radius: avatarSize / 2,
                        backgroundImage: const NetworkImage('https://picsum.photos/200'),
                      ),
                    ),
                    // 标题
                    Positioned(
                      left: 16 + avatarSize + 12,
                      top: titleTopOffset,
                      child: Text(
                        'Telegram',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: titleFontSize,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ],
                );
              },
            ),
            // 右侧操作按钮
            actions: [
              IconButton(icon: const Icon(Icons.search), onPressed: () {}),
              IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}),
            ],
          ),
          // 测试滚动内容
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(title: Text('Item $index')),
              childCount: 50,
            ),
          ),
        ],
      ),
    );
  }
}

关键细节说明

  • SliverAppBar的pinned: true确保滚动时AppBar始终固定在顶部,expandedHeight定义展开状态的高度,minHeight默认使用标准工具栏高度kToolbarHeight。
  • 通过LayoutBuilder获取当前AppBar的实时高度,计算出scrollPercentage,以此为基准线性插值调整头像、标题的尺寸和位置,实现平滑过渡。
  • 用Positioned组件精确控制元素位置,可根据需求调整背景色、元素变化幅度等参数,完全匹配Telegram的视觉效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:55:47