使用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
相关产品推荐
相关产品推荐

