美文网首页
从零开始用flutter写一个完整应用⑹:路由,页面跳转

从零开始用flutter写一个完整应用⑹:路由,页面跳转

作者: 逃离_102 | 来源:发表于2022-06-27 23:13 被阅读0次

说明

路由,页面跳转是一个应用最基本功能之一。页面跳转包括2个基本问题,一是跳转时的参数传递;二是页面返回时参数回传

跳转方式

flutter有2种跳转方式:1,直接push,pop;2,pushName,pop

直接push,pop

步骤:

  1. 创建两个路由;
  2. 用 Navigator.push() 跳转到第二个路由;
  3. 用 Navigator.pop() 回退到第一个路由

Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const SecondRoute()),
  );

Navigator.pop(context);

pushName,pop

步骤:

  1. 创建两个界面
  2. 定义路由
  3. 使用 Navigator.pushNamed() 跳转到第二个界面
  4. 使用 Navigator.pop() 返回到第一个界面
MaterialApp(
  title: 'Named Routes Demo',
  
  // 使用“/”命名路由来启动应用(Start the app with the "/" named route. In our case, the app will start)
  // 在这里,应用将从 FirstScreen Widget 启动(on the FirstScreen Widget)
  initialRoute: '/',
  routes: {
    '/': (context) => const FirstScreen(),
    '/second': (context) => const SecondScreen(),
  },
)

// 在 `FirstScreen` Widget中(Within the `FirstScreen` Widget)
onPressed: () {
  // 使用命名路由跳转到第二个界面(Navigate to the second screen using a named route)
  Navigator.pushNamed(context, '/second');
}

// 在 SecondScreen Widget 中(Within the SecondScreen Widget)
onPressed: () {
  // 通过从堆栈弹出当前路由(Navigate back to the first screen by popping the current route)
  // 来返回到第一个界面(off the stack)
  Navigator.pop(context);
}

给特定的route传参

步骤:
1,定义需要传递的参数
2,创建组件来获取参数
3,把组件注册到路由表中
4,导航到组件

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(
      routes: {
        ExtractArgumentsScreen.routeName: (context) =>
            const ExtractArgumentsScreen(),
      }, //把组件注册到路由表中
      
      onGenerateRoute: (settings) {
        if (settings.name == PassArgumentsScreen.routeName) {
          
          final args = settings.arguments as ScreenArguments;

          return MaterialPageRoute(
            builder: (context) {
              return PassArgumentsScreen(
                title: args.title,
                message: args.message,
              );
            },
          );
        }
      },

      title: 'Navigation with Arguments',
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                // 导航到组件
                Navigator.pushNamed(
                  context,
                  ExtractArgumentsScreen.routeName,
                  arguments: ScreenArguments(
                    'Extract Arguments Screen',
                    'This message is extracted in the build method.',
                  ),
                );
              },
              child: const Text('导航到提取参数的屏幕'),
            ),
            
            ElevatedButton(
              onPressed: () {
                // 导航到组件
                Navigator.pushNamed(
                  context,
                  PassArgumentsScreen.routeName,
                  arguments: ScreenArguments(
                    'Accept Arguments Screen',
                    'This message is extracted in the onGenerateRoute '
                        'function.',
                  ),
                );
              },
              child: const Text('导航到接受参数的命名'),
            ),
          ],
        ),
      ),
    );
  }
}

// 创建组件,从 `ScreenArguments` 提取 `title` 和 `message` 参数并展示。
//为了访问 `ScreenArguments`,可以使用 ModalRoute.of() 方法。这个方法返回的是当前路由及其携带的参数
class ExtractArgumentsScreen extends StatelessWidget {
  const ExtractArgumentsScreen({super.key});

  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {
   
    final args = ModalRoute.of(context)!.settings.arguments as ScreenArguments;

    return Scaffold(
      appBar: AppBar(
        title: Text(args.title),
      ),
      body: Center(
        child: Text(args.message),
      ),
    );
  }
}
//使用 onGenerateRoute 提取参数
class PassArgumentsScreen extends StatelessWidget {
  static const routeName = '/passArguments';

  final String title;
  final String message;

  const PassArgumentsScreen({
    super.key,
    required this.title,
    required this.message,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text(message),
      ),
    );
  }
}

// 定义需要传递的参数
class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

从一个页面回传数据

步骤:
1,创建主屏界面
2,添加按钮,点击时跳转到选择界面
3,在选择界面显示两个按钮
4,当任意一个按钮被点击,关闭选择界面回退到主屏界面
5,在主屏界面显示 snackbar ,展示选中的项目

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      title: 'Returning Data',
      home: HomeScreen(),
    ),
  );
}
//创建主屏界面
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Returning Data Demo'),
      ),
      body: const Center(
        child: SelectionButton(),
      ),
    );
  }
}
//添加按钮,点击时跳转到选择界面
class SelectionButton extends StatelessWidget {
  const SelectionButton({super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        _navigateAndDisplaySelection(context);
      },
      child: const Text('Pick an option, any option!'),
    );
  }

  Future<void> _navigateAndDisplaySelection(BuildContext context) async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const SelectionScreen()),
    );
    //在主屏界面显示一个 snackbar,展示选中的项目
    ScaffoldMessenger.of(context)
      ..removeCurrentSnackBar()
      ..showSnackBar(SnackBar(content: Text('$result')));
  }
}
//在选择界面显示两个按钮
class SelectionScreen extends StatelessWidget {
  const SelectionScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Pick an option'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: ElevatedButton(
                onPressed: () {
                  Navigator.pop(context, 'Yep!');
                },
                child: const Text('Yep!'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: ElevatedButton(
                onPressed: () {
                  Navigator.pop(context, 'Nope.');
                },
                child: const Text('Nope.'),
              ),
            )
          ],
        ),
      ),
    );
  }
}

传递数据到新页面

步骤:
1, 定义一个描述待办事项的数据类
2, 显示待办事项
3,创建一个显示待办事项详细信息的界面
4,传递数据并跳转到待办事项详细信息界面

import 'package:flutter/material.dart';

//定义一个描述待办事项的数据类
class Todo {
  final String title;
  final String description;

  const Todo(this.title, this.description);
}

void main() {
  runApp(
    MaterialApp(
      title: 'Passing Data',
      home: TodosScreen(
        //创建待办事项列表
        todos: List.generate(
          20,
          (i) => Todo(
            'Todo $i',
            'A description of what needs to be done for Todo $i',
          ),
        ),
      ),
    ),
  );
}
//创建一个待办页面显示待办事件列表
class TodosScreen extends StatelessWidget {
  const TodosScreen({super.key, required this.todos});

  final List<Todo> todos;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Todos'),
      ),
      body: ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(todos[index].title),
            
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(todo: todos[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }
}
//创建一个显示待办事项详细信息的界面
class DetailScreen extends StatelessWidget {
 
  const DetailScreen({super.key, required this.todo});

  final Todo todo;

  @override
  Widget build(BuildContext context) {
    // 传递数据并跳转到待办事项详细信息界面
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Text(todo.description),
      ),
    );
  }
}

页面跳转基础用法就这些了,过渡动画等其他东西在下篇文章里

相关文章

网友评论

      本文标题:从零开始用flutter写一个完整应用⑹:路由,页面跳转

      本文链接:https://www.haomeiwen.com/subject/jbnlmrtx.html