Flutter Navigation

Tóm tắt: trong bài viết này các bạn sẽ được học về Flutter navigation để điều hướng từ 1 màn hình này qua màn hình khác và quay trở lại

Giới thiệu về Flutter navigation

Thông thường, ứng dụng chứa nhiều màn hình để hiển thị thông tin khác nhau. Ví dụ: ứng dụng thương mại điện tử có thể có màn hình hiển thị danh sách sản phẩm. Khi người dùng chạm vào một sản phẩm, một màn hình mới sẽ hiển thị chi tiết sản phẩm

Flutter navigation quản lý các màn hình dưới dạng một ngăn xếp và hiển thị màn hình nằm trên cùng của ngăn xếp.

Stack

Một stack là một cấu trúc dữ liệu đóng vai trò là tập hợp các mục với hai thao tác chính:

  • Push: thêm một mục vào ngăn xếp.
  • Pop: xóa mục được thêm gần đây nhất khỏi ngăn xếp.

Thứ tự mà một mục được thêm vào hoặc xóa khỏi ngăn xếp được gọi là vào sau, ra trước hoặc viết tắt là LIFO.

Navigator

Flutter navigation hoạt động giống như một ngăn xếp các màn hình. Trong Flutter, các màn hình và trang thường được gọi là các tuyến đường, là các widget.

Flutter sử dụng đối tượng Navigator để điều hướng từ tuyến này sang tuyến khác. Đối tượng Navigator giống như một tập hợp các tuyến đường, có hai phương thức chính:

  • push() – navigate to a new route by adding a route to the stack .
  • pop() – xóa tuyến đường hiện tại khỏi ngăn xếp

Ví dụ Flutter navigation

Ví dụ sau đây cho thấy cách sử dụng đối tượng Navigator để điều hướng đến một tuyến đường mới và quay lại

import 'package:flutter/material.dart';

void main() {
  runApp(
      const MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Navigation',
        home: 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: ElevatedButton(
          child: const Text('Go to the detail screen'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const DetailScreen()),
            );
          },
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Detail screen'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}

Nó làm việc như thế nào.

Đầu tiên, tạo 2 màn hình: HomeScreen và DetailScreen.

Tiếp theo, màn hình HomeScreen có 1 button. Khi nhấp vào button, gọi phương thức push() của đối tượng Navigator để điều hướng tới 1 tuyến đường mới.

onPressed: () {
  Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const SecondScreen()),
  );
}

Phương thức push() chấp nhận tham số đầu tiên là BuildContext hiện tại và tham số thứ 2 là một đối tượng MaterialPageRoute.

Đối tượng MaterialPageRoute chỉ định tuyến đường mới được điều hướng tới.

Thứ ba, màn hình DetailScreen cũng có 1 nút. Khi nút được bấm, quay trở lại màn hình HomeScreen bởi việc gọi phương thức pop() của đối tượng Navigator:

Navigator.pop(context);

Phương thức pop() chấp nhận tham số là một context của BuildContext hiện tại.

Gởi dữ liệu tới 1 tuyến đường mới

Ví dụ sau minh họa cách gửi một chuỗi từ HomeScreen đến DetailScreen:

import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(
    debugShowCheckedModeBanner: false,
    title: 'Flutter Navigation',
    home: 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: ElevatedButton(
          child: const Text('Go to the detail screen'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const DetailScreen(
                    message: 'This is a message from the home screen'),
              ),
            );
          },
        ),
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  final String message;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Detail screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(message),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: const Text('Go back!'),
            ),
          ],
        ),
      ),
    );
  }
}

Nó làm việc như thế nào.

Đầu tiên, thêm 1 thuộc tính message tới màn hình DetailScreen và một hàm khơi tạo chấp nhận thêm 1 tham số đầu this.message vào const DetailScreen({super.key, required this.message});

Thứ 2, thêm 1 Text widget để hiện thị thuộc tính message lên

Thứ 3, Khi gọi phương thức push() của đối tượng Navigator, gởi một chuỗi tới hàm khởi tạo DetailScreen.

Gởi dữ liệu trở lại tuyến đường trước đó

Ví dụ sau sẽ minh họa làm thế nào để truyền dữ liệu từ màn hình DetailScreen trở lại màn hình HomeScreen:

import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(
    debugShowCheckedModeBanner: false,
    title: 'Flutter Navigation',
    home: 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: ElevatedButton(
          child: const Text('Go to the detail screen'),
          onPressed: () async {
            var message = await Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const DetailScreen(
                    message: 'This is a message from the home screen'
                ),
              ),
            );
            print(message);
          },
        ),
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  final String message;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Detail screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(message),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context, 'This is a message from the Detail screen');
              },
              child: const Text('Go back!'),
            ),
          ],
        ),
      ),
    );
  }
}

Đầu tiên, truyền 1 chuỗi tới tham số thứ 2 của phương thức pop() của đối tượng Navigator từ màn hình DetailScreen:

onPressed: () {
	Navigator.pop(
		context, 
		'This is a message from the Detail screen'
	);
}

Thứ 2, thay đổi hàm onPressed thành hàm async bởi vì chúng ta sẽ sử dụng từ khóa await bên trong nó.

Phương thức push() trả về 1 đối tượng Future vì vậy chúng ta sử dụng từ khóa await để đợi dữ liệu trước khi nhận được dữ liệu trả về từ màn hình DetailScreen.

Để demo cho việc này, chúng tôi in ra chuỗi trả về.

onPressed: () async {
	var message = await Navigator.push(
		context,
                MaterialPageRoute(builder: (context) => const DetailScreen(message: 'This is a message from the home screen')),
	);
	print(message);
}

Kết luận

  • Sử dụng đối tượng Navigator để điều hướng từ 1 tuyến đường tới 1 tuyến đường khác.
  • Sử dụng phương thức push() của đối tượng Navigator để điều hướng tới 1 tuyến đường mới.
  • Sử dụng phương thức pop() của đối tượng Navigator để quay trở lại tuyến đường trước đó.

Nguồn: https://www.darttutorial.org/flutter-tutorial/flutter-navigation/

Happy coding 🙂

5/5 - (3 votes)

You May Also Like

About the Author: truongluu

Leave a Reply

Your email address will not be published. Required fields are marked *