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

Flutter PageView页面间无跳转数据传递及页面切换实现

Flutter PageView 页面间数据传递解决方案

需求说明

需要在PageView组件内实现页面间数据传递,无需跳转新页面:在page页面的弹窗输入用户名并点击OK后,滑动切换到codeforce页面,同时将用户名传递过去展示。当前使用Navigator.push()会替换屏幕,不符合需求。

解决方案

核心思路是状态提升,把需要共享的用户名数据存放在PageView的父组件(HomeScreen)的状态中,子页面通过回调更新父组件状态,目标页面直接使用父组件的状态值。

实现步骤

  • 在HomeScreen的状态类中添加存储用户名的变量
  • 给page组件添加回调函数,用于传递输入的用户名
  • 修改codeforce组件,接收父组件传递的用户名并展示
  • 调整page页面弹窗OK按钮的逻辑,调用回调更新状态后切换页面

修改后的代码

HomeScreen代码

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final PageController _controller = PageController();
  int _index = 0;
  // 存储CodeForces用户名
  String _cfUsername = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        controller: _controller,
        children: [
          Page(
            controller: _controller,
            onUsernameSubmitted: (username) {
              setState(() {
                _cfUsername = username;
              });
            },
          ),
          const Codechef(),
          Codeforce(sub: _cfUsername),
        ],
        onPageChanged: (page) {
          setState(() {
            _index = page;
          });
        },
      ),
      bottomNavigationBar: Container(
        color: const Color.fromARGB(255, 19, 63, 99),
        child: Padding(
          padding: const EdgeInsets.all(8),
          child: GNav(
            tabs: const [
              GButton(
                icon: Icons.home,
                text: "Home",
              ),
              GButton(
                icon: Cp.codechef_svgrepo_com,
                text: "CodeChef",
              ),
              GButton(
                icon: Cp.codeforces_svgrepo_com,
                text: "CodeForces",
              )
            ],
            onTabChange: (index) {
              setState(() {
                _index = index;
              });
              _controller.jumpToPage(index);
            },
            color: Colors.green,
            backgroundColor: const Color.fromARGB(255, 22, 64, 98),
            activeColor: Colors.white,
            tabBackgroundColor: const Color.fromARGB(255, 18, 44, 65),
            gap: 20,
            padding: const EdgeInsets.all(20),
            rippleColor: const Color.fromARGB(255, 51, 23, 23),
            selectedIndex: _index,
          ),
        ),
      ),
    );
  }
}

Page页面代码

import 'package:flutter/material.dart';

class Page extends StatefulWidget {
  final PageController controller;
  final Function(String) onUsernameSubmitted;

  const Page({Key? key, required this.controller, required this.onUsernameSubmitted}) : super(key: key);

  @override
  State<Page> createState() => _PageState();
}

class _PageState extends State<Page> {
  final TextEditingController _textFieldController = TextEditingController();
  late String _codeDialog;
  bool _en = false;

  Future<void> _displayTextInputDialog(BuildContext context) {
    return showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            backgroundColor: const Color.fromARGB(255, 55, 74, 90),
            title: const Text(
              'UserName',
              style: TextStyle(color: Colors.white),
            ),
            content: TextFormField(
              onChanged: (value) {
                setState(() {
                  _codeDialog = value;
                });
              },
              controller: _textFieldController,
              decoration: const InputDecoration(
                hintText: "Enter a valid user name",
                hintStyle: TextStyle(color: Colors.white),
              ),
              style: const TextStyle(
                color: Colors.white,
              ),
              validator: (value) {
                if (value == null || value.isEmpty) {
                  return "Enter User name";
                }
                return null;
              },
            ),
            actions: <Widget>[
              ElevatedButton(
                child: const Text(
                  'CANCEL',
                  style: TextStyle(color: Colors.white),
                ),
                onPressed: () {
                  Navigator.pop(context);
                },
                style: ElevatedButton.styleFrom(primary: Colors.red),
              ),
              ElevatedButton(
                child: const Text(
                  'OK',
                  style: TextStyle(color: Colors.white),
                ),
                onPressed: () {
                  setState(() {
                    _en = true;
                    // 调用回调传递用户名
                    widget.onUsernameSubmitted(_codeDialog);
                    // 跳转到CodeForces页面
                    widget.controller.jumpToPage(2);
                  });
                  Navigator.pop(context);
                },
                style: ElevatedButton.styleFrom(primary: Colors.green),
              ),
            ],
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Container(
        child: Center(
          child: GridView(
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2, crossAxisSpacing: 10),
            children: [
              Container(
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    color: const Color.fromARGB(255, 97, 78, 78)),
                child: Column(
                  children: [
                    const Icon(
                      Cp.codechef_svgrepo_com,
                      size: 100,
                    ),
                    const Text("CodeChef",
                        style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.bold,
                          color: Color.fromARGB(255, 166, 201, 229),
                        ))
                  ],
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  crossAxisAlignment: CrossAxisAlignment.center,
                ),
              ),
              InkWell(
                onTap: () async {
                  await _displayTextInputDialog(context);
                },
                child: Container(
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(10),
                      color: const Color.fromARGB(255, 40, 83, 118)),
                  child: Column(
                    children: [
                      const Icon(
                        Cp.codeforces_svgrepo_com,
                        size: 100,
                      ),
                      const Text(
                        "CodeForces",
                        style: TextStyle(
                            fontSize: 20,
                            fontWeight: FontWeight.bold,
                            color: Color.fromARGB(255, 166, 201, 229)),
                      ),
                      _en ? Text(_codeDialog) : const Text("")
                    ],
                    mainAxisAlignment: MainAxisAlignment.center,
                  ),
                ),
              )
            ],
            shrinkWrap: true,
          ),
        ),
      ),
    );
  }
}

Codeforce页面示例

class Codeforce extends StatelessWidget {
  final String sub;

  const Codeforce({Key? key, required this.sub}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        sub.isEmpty ? "请输入用户名" : "CodeForces用户名:$sub",
        style: const TextStyle(fontSize: 20),
      ),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:15:33