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

Flutter新手求助:如何实现点击按钮弹出水平抽屉效果?

Flutter实现点击按钮弹出水平抽屉效果

你要的这种水平滑出的抽屉效果,用Flutter原生动画组件就能实现,核心是通过AnimationController配合SlideTransition控制面板的滑入滑出,下面是完整的实现示例:

实现代码

import 'package:flutter/material.dart';

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

  @override
  State<HorizontalDrawerDemo> createState() => _HorizontalDrawerDemoState();
}

class _HorizontalDrawerDemoState extends State<HorizontalDrawerDemo> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Offset> _slideAnimation;
  bool _isDrawerOpen = false;

  @override
  void initState() {
    super.initState();
    // 初始化动画控制器,设置动画时长
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
    // 定义从右侧滑入的动画曲线
    _slideAnimation = Tween<Offset>(
      begin: const Offset(1, 0),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInOut,
    ));
  }

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

  // 切换抽屉显示/隐藏状态
  void _toggleDrawer() {
    setState(() {
      _isDrawerOpen = !_isDrawerOpen;
    });
    _isDrawerOpen ? _controller.forward() : _controller.reverse();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('水平抽屉示例'),
        actions: [
          // 触发抽屉的按钮
          IconButton(
            icon: const Icon(Icons.menu),
            onPressed: _toggleDrawer,
          ),
        ],
      ),
      body: Stack(
        children: [
          // 主内容区域
          const Center(
            child: Text('主页面内容'),
          ),
          // 水平抽屉面板
          SlideTransition(
            position: _slideAnimation,
            child: Container(
              width: MediaQuery.of(context).size.width * 0.7, // 抽屉宽度占屏幕70%
              color: Colors.white,
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      '抽屉标题',
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 20),
                    // 抽屉内选项示例
                    ListTile(
                      leading: const Icon(Icons.settings),
                      title: const Text('设置'),
                      onTap: _toggleDrawer,
                    ),
                    ListTile(
                      leading: const Icon(Icons.person),
                      title: const Text('个人中心'),
                      onTap: _toggleDrawer,
                    ),
                  ],
                ),
              ),
            ),
          ),
          // 抽屉打开时的遮罩层,点击可关闭抽屉
          if (_isDrawerOpen)
            GestureDetector(
              onTap: _toggleDrawer,
              child: Container(color: Colors.black.withOpacity(0.5)),
            ),
        ],
      ),
    );
  }
}

// 调用示例
void main() {
  runApp(const MaterialApp(home: HorizontalDrawerDemo()));
}

关键说明

  • SlideTransition:通过Offset参数控制抽屉的滑动位置,Offset(1,0)表示完全在屏幕右侧外,Offset.zero表示完全显示
  • AnimationController:管理动画的播放状态,记得在组件销毁时调用dispose()释放资源
  • Stack:实现主内容、抽屉、遮罩层的层叠布局,让抽屉在主内容上方滑出
  • 若需要从左侧滑出,只需把Tween的begin参数改为const Offset(-1, 0)即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 05:15:37