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

Flutter实现点击图标切换中间Container/Widget(保留AppBar)

在Flutter中实现AppBar固定、中间内容切换的方案

要实现点击前进/后退图标时仅切换页面中间内容、保留AppBar不变,核心是让AppBar作为父布局的固定部分,中间内容区域根据状态动态切换,以下是几种常用的实现方式:

1. 使用IndexedStack(保留页面状态)

适合需要保留页面状态的场景(比如切换回页面时不想重新加载表单内容),IndexedStack会一次性加载所有子Widget,切换时仅显示对应索引的内容。

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

  @override
  State<FixedAppBarPage> createState() => _FixedAppBarPageState();
}

class _FixedAppBarPageState extends State<FixedAppBarPage> {
  int _currentPageIndex = 0;
  // 定义所有需要切换的中间内容
  final List<Widget> _pageContents = const [
    Center(child: Text("第一页内容")),
    Center(child: Text("第二页内容")),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("固定AppBar示例"),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            if (_currentPageIndex > 0) {
              setState(() => _currentPageIndex--);
            }
          },
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.arrow_forward),
            onPressed: () {
              if (_currentPageIndex < _pageContents.length - 1) {
                setState(() => _currentPageIndex++);
              }
            },
          ),
        ],
      ),
      // 用IndexedStack承载切换内容
      body: IndexedStack(
        index: _currentPageIndex,
        children: _pageContents,
      ),
    );
  }
}

2. 使用PageView(带切换动画)

适合需要流畅切换动画、支持左右滑动切换的场景,PageView默认懒加载,性能更优,还能通过PageController精准控制页面切换。

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

  @override
  State<FixedAppBarWithPageView> createState() => _FixedAppBarWithPageViewState();
}

class _FixedAppBarWithPageViewState extends State<FixedAppBarWithPageView> {
  final PageController _pageController = PageController(initialPage: 0);
  int _currentPageIndex = 0;

  @override
  void dispose() {
    _pageController.dispose(); // 记得释放控制器
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("固定AppBar+PageView"),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            if (_currentPageIndex > 0) {
              _pageController.previousPage(
                duration: const Duration(milliseconds: 300),
                curve: Curves.easeInOut,
              );
            }
          },
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.arrow_forward),
            onPressed: () {
              if (_currentPageIndex < 1) { // 假设只有2个页面
                _pageController.nextPage(
                  duration: const Duration(milliseconds: 300),
                  curve: Curves.easeInOut,
                );
              }
            },
          ),
        ],
      ),
      body: PageView(
        controller: _pageController,
        onPageChanged: (index) {
          setState(() => _currentPageIndex = index);
        },
        children: const [
          Center(child: Text("第一页内容")),
          Center(child: Text("第二页内容")),
        ],
      ),
    );
  }
}

3. 条件渲染(简单场景)

适合页面数量少、不需要保留状态的纯展示场景,直接根据当前索引切换显示的Widget。

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

  @override
  State<FixedAppBarWithConditionalRender> createState() => _FixedAppBarWithConditionalRenderState();
}

class _FixedAppBarWithConditionalRenderState extends State<FixedAppBarWithConditionalRender> {
  int _currentPageIndex = 0;

  // 根据索引返回对应内容
  Widget _getCurrentContent() {
    switch (_currentPageIndex) {
      case 0:
        return const Center(child: Text("第一页内容"));
      case 1:
        return const Center(child: Text("第二页内容"));
      default:
        return const Center(child: Text("默认页面"));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("固定AppBar+条件渲染"),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            if (_currentPageIndex > 0) {
              setState(() => _currentPageIndex--);
            }
          },
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.arrow_forward),
            onPressed: () {
              if (_currentPageIndex < 1) {
                setState(() => _currentPageIndex++);
              }
            },
          ),
        ],
      ),
      body: _getCurrentContent(),
    );
  }
}

方案选择建议

  • 需保留页面状态(如表单输入):选IndexedStack
  • 需切换动画、支持滑动:选PageView
  • 页面简单、无需状态保留:选条件渲染

内容的提问来源于stack exchange,提问作者Thuan Le Van

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 11:52:46