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

Flutter实现仿Telegram自定义可拖拽BottomSheet

实现Telegram风格的BottomSheet头部动态展开效果

Telegram应用有个实用特性:其内置的BottomSheet在向上滑动到距离顶部特定距离时,会自动增大头部高度并显示AppBar。我尝试使用DraggableScrollableSheet来实现该交互,即使借助ChatGPT的帮助也没能达成预期效果,以下是我的示例代码和效果示意图:

效果示意图

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Draggable Bottom Sheet',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: DraggableBottomSheetExample(),
    );
  }
}

class DraggableBottomSheetExample extends StatefulWidget {
  @override
  _DraggableBottomSheetExampleState createState() =
      _DraggableBottomSheetExampleState();
}

class _DraggableBottomSheetExampleState
    extends State<DraggableBottomSheetExample> with TickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _textSizeAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 300),
    );
    _textSizeAnimation = Tween<double>(begin: 24.0, end: 48.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Curves.easeInOut,
      ),
    );
  }

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

  void _onScroll(double offset) {
    if (offset >= 0.8 && !_controller.isAnimating && !_controller.isCompleted) {
      _controller.forward();
    } else if (offset < 0.8 && !_controller.isAnimating && _controller.isCompleted) {
      _controller.reverse();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Draggable Bottom Sheet Example'),
      ),
      body: Stack(
        children: <Widget>[
          Center(
            child: ElevatedButton(
              onPressed: () {
                showModalBottomSheet(
                  context: context,
                  isScrollControlled: true,
                  builder: (BuildContext context) {
                    return DraggableScrollableSheet(
                      initialChildSize: 0.3,
                      minChildSize: 0.1,
                      maxChildSize: 0.8,
                      builder: (context, scrollController) {
                        scrollController.addListener(() {
                          _onScroll(scrollController.position.pixels /
                              scrollController.position.maxScrollExtent);
                        });

                        return Container(
                          color: Colors.blueGrey[200],
                          child: SingleChildScrollView(
                            controller: scrollController,
                            child: Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: <Widget>[
                                  AnimatedBuilder(
                                    animation: _controller,
                                    builder: (context, child) {
                                      return Text(
                                        'Draggable Bottom Sheet',
                                        style: TextStyle(
                                          fontSize: _textSizeAnimation.value,
                                          fontWeight: FontWeight.bold,
                                        ),
                                      );
                                    },
                                  ),
                                  SizedBox(height: 16),
                                  Text(
                                    'Swipe up to expand or down to collapse.',
                                    style: TextStyle(fontSize: 16),
                                  ),
                                  SizedBox(height: 16),
                                  // Add more content here
                                  Container(
                                    height: 500,
                                    color: Colors.blue[100],
                                  ),
                                ],
                              ),
                            ),
                          ),
                        );
                      },
                    );
                  },
                );
              },
              child: Text('Show Draggable Bottom Sheet'),
            ),
          ),
        ],
      ),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:25:18