Google

Flutter Navigation Tutorial (Part 1)

Giới thiệu

Xin chào các bạn hôm nay mình xin phép trình bày về Flutter Navigation. Flutter là một cross-platform development SDK từ Google cho phép bạn nhanh chóng phát triển app trên iOS và Android từ một source code. Trong tutorial lần này mình sẽ giới thiệu cách implements navigation giữa 2 màn hình cụ thể như sau:

  • Routes and navigation
  • Popping off the stack
  • Returning a value from a route
  • Custom navigation transitions

Bài viết được tham khảo từ nguồn:

https://flutter.io/tutorials/

https://www.raywenderlich.com/110-flutter-navigation-tutorial

Getting Started

Trước tiên ta sẽ download the starter tại đây Trong turotial này mình sẽ sử dụng Android Studio. Ngoài ra có thể sử dụng VS Code, IntelliJ IDEA.

Mở Start project in Android Studio bằng cách chọn File -> Open sau đó chọn folder của start project file.

Khi build thử trên iOS Simulator:

Khi build thử trên Android Studio:

Second Screen

Màn hình thứ 2 sẽ là màn hình detail cho mỗi member. Trước tiên ta sẽ tạo class Model cho Member. Ta tạo file mới có tên là Member.dart và implement như sau:

class Member {
  final String login;
  final String avatarUrl;

  Member(this.login, this.avatarUrl) {
    if (login == null) {
      throw new ArgumentError("login of Member cannot be null. "
          "Received: '$login'");
    }

    if (avatarUrl == null) {
      throw new ArgumentError("avatarUrl of Member cannot be null. "
          "Received: '$avatarUrl'");
    }
  }
}

Tiếp theo mình sẽ tạo class DetaiViewController cho màn hình thứ 2. Ta tạo file mới có tên là DetailViewController.dart. Ta sẽ import model vào

import 'Member.dart';

Tiếp theo ta sẽ import statements và 1 subclass của StatefulWidget là DetailView

import 'package:flutter/material.dart';
import 'Member.dart';

class DetaiView extends StatefulWidget {
  final Member member;

  DetaiView(this.member) {
    if (member == null) {
      throw new ArgumentError('member of DetailView');
    }
  }

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new DetaiViewState(member);
  }
}

Mỗi một DetaiView cho từng Member thì được sử dụng một DetaiViewState. Add thêm class DetailViewState cho State của DetaiView.

class DetaiViewState extends State<DetaiView> {
  final Member memeber;
  DetaiViewState(this.memeber);
}

Tiếp theo ta sẽ override lại hàm func build():

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('DetailViewState'),
      ),
      body: new Padding(
          padding: new EdgeInsets.all(16.0),
          child: new Image.network(memeber.avatarUrl)
          ),
    );
  }

Routes

Ta quay về với class main.dart và import DetailViewController.dart Tiếp theo ta add 1 private func _pushMember() tới GHFlutterState

  void _pushMember(Member member) {
    Navigator.of(context).push(
      new MaterialPageRoute(
          builder: (context) => new DetaiView(member)
      )
    );
  }

Bây giờ ta cần phải call được func _pushMember() khi user tap và row trong list of members. Ta sẽ update lại trong hàm _buildRow() trong GHFlutterState và add thêm thuộc tính onTap tới ListTile

  Widget _buildRow(int i) {
    return new Padding(
      padding: const EdgeInsets.all(16.0),
      child: new ListTile(
        title: new Text("${_members[i].login}", style: _biggerFont),
        leading: new CircleAvatar(
          backgroundColor: Colors.green,
          backgroundImage: new NetworkImage(_members[i].avatarUrl),
        ),
        onTap: (){
          _saveMember.add(_members[i]);
          _pushMember(_members[i]);
        },
      ),
    );
  }

Và đây là kết quả trên iOS simulator:

Và trên Android emulator:

Popping the stack

Cơ chế hoạt động của Navigation trong Flutter trên cơ chế Stack(Push và Pop) Thêm một IconButton tới DetaiViewState trong func build() và phải add thêm 1 hàng trong Widget

@override
Widget build(BuildContext context) {
  return new Scaffold (
    appBar: new AppBar(
      title: new Text(member.login),
    ),
    body: new Padding(
      padding: new EdgeInsets.all(16.0),
      // Add Column here:
      child: new Column(
        children: [
          new Image.network(member.avatarUrl),
          new IconButton(
            icon: new Icon(Icons.arrow_back, color: Colors.green, size: 48.0),
            onPressed: () { Navigator.pop(context); }
            ),
        ]),
    )
  );
}

Tổng kết

Cảm ơn các bạn đã theo dõi tutorial này. Bài tiếp theo mình sẽ giới thiệu cũng như demo tiếp về phần Returning a value và Custom Transitions.

Registration Login
Sign in with social account
or
Lost your Password?
Registration Login
Sign in with social account
or
A password will be send on your post
Registration Login
Registration