본문 바로가기

flutter

[Flutter] Flutter Navigator 사용법 (4)

Photo by  Niclas Illg on Unsplash

 

새로운 화면으로 데이터 보내기

종종 새로운 화면으로 단순히 이동하는 것 뿐만 아니라 데이터를 넘겨주어야 할 때도 있음. 예를 들어, 사용자가 선택한 아이템에 대한 정보를 같이 넘겨주는 경우가 있음. 예제에서는 Todo 리스트를 만들고 Todo를 선택하면 새로운 화면(위젯)으로 이동하면서 선택한 to do에 대한 정보를 표시함.

  1. Todo 클래스를 정의함.
  2. Todo 리스트를 표시함.
  3. Todo에 대한 상세 정보를 보여줄 수 있는 화면을 생성.
  4. 상세 화면으로 이동하면서 데이터를 전달.
  5. Todo 클래스를 정의. Todo를 표현하기 위한 간단한 정보를 표시함. 이 예제에서는 두 가지의 데이터를 갖고 있는 클래스를 정의함.
class Todo {
  final String title;
  final String description;  Todo(this.title, this.description);
}

Todo 리스트를 표시함. 예제에서는 20개의 todo를 생성하고 ListView를 사용하여 Todo 리스트 생성함.

final todos = List<Todo>.generate(
  20,
  (i) => Todo(
        'Todo $i',
        'A description of what needs to be done for Todo $i',
      ),
);
ListView를 사용하여 Todo 리스트 보여주기
content_copy
ListView.builder(
  itemCount: todos.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(todos[index].title),
    );
  },
);

20개의 Todo를 생성하여 ListView에 표시함.

Todo에 대한 상세 정보를 보여줄 수 있는 화면을 생성. 예제에서 두 번째 화면의 제목은 Todo의 제목을 포함하며 본문에는 상세 설명을 표시함.

class DetailScreen extends StatelessWidget {
  // Todo를 들고 있을 필드를 선언.
  final Todo todo;  // 생성자 매개변수로 Todo를 받도록 함.
  DetailScreen({Key key, @required this.todo}) : super(key: key);  @override
  Widget build(BuildContext context) {
    // UI를 그리기 위해 Todo를 사용.
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text(todo.description),
      ),
    );
  }
}

상세 화면으로 이동하면서 데이터를 전달함.

예제에서는 사용자가 Todo 리스트 중 하나를 선택했을 때, DetailsScreen으로 화면 전환하고 동시에 DetailsScreen에 Todo를 전달.

사용자의 탭 동작을 감지하기 위해, ListTile 위젯에 onTap 콜백을 작성하고 onTap 콜백 내에서 다시 한 번 Navigator.push 메서드를 사용함.

ListView.builder(
  itemCount: todos.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(todos[index].title)
      // DetailScreen을 생성하고 현재 todo를 같이 전달.
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => DetailScreen(todo: todos[index]),
          ),
        );
      },
    );
  },
);

완성된 예제

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';class Todo {
  final String title;
  final String description;  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 {
  final List<Todo> todos;  TodosScreen({Key key, @required this.todos}) : super(key: key);  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: 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 {
  // Todo를 들고 있을 필드를 선언.
  final Todo todo;  // 생성자는 Todo를 인자로 받음.
  DetailScreen({Key key, @required this.todo}) : super(key: key);  @override
  Widget build(BuildContext context) {
    // UI를 그리기 위해 Todo를 사용합니다.
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text(todo.description),
      ),
    );
  }
}