List Applications are everywhere. Social Media Apps, Note Taking Apps. Yes, the list won’t end.

So if you are trying to make a List App and want to navigate to a new screen when the user taps.

This post will definitely good for you.

1. ListView Navigation: Navigate To New Screen.

flutter listview navigation

In this simple example, you will learn how to navigate to a different screen through ListTile onTap function.

  • I have used 3 ListTiles. When the user taps a ListTile, it calls onTap Function.
  • Then Navigator pushes the screen.

Below is the code.

ListTile(
            title: Text('First Screen'),
            trailing: Icon(Icons.keyboard_arrow_right_sharp),
//onTap calls When ListTile Taps
            onTap: () {
//Navigator pushes FirstScreen.
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => FirstScreen(),
                ),
              );
            },
          ),

Full source code is given below.


import 'package:flutter/material.dart';
import 'first_screen.dart';
import 'second_screen.dart';
import 'third_screen.dart';

void main() {
  runApp(
    MyApp(),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter ListView Navigation I',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyListView(),
    );
  }
}

class MyListView extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter ListView Navigation I'),
      ),
      body: ListView(
        children: [
          ListTile(
            title: Text('First Screen'),
            trailing: Icon(Icons.keyboard_arrow_right_sharp),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => FirstScreen(),
                ),
              );
            },
          ),
          ListTile(
            title: Text('Second Screen'),
            trailing: Icon(Icons.keyboard_arrow_right_sharp),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => SecondScreen(),
                ),
              );
            },
          ),
          ListTile(
            title: Text('Third Screen'),
            trailing: Icon(Icons.keyboard_arrow_right_sharp),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => ThirdScreen(),
                ),
              );
            },
          ),
        ],
      ),
    );
  }
}


Next, You have to make 3 Screens. FirstScreen, SecondScreen and ThirdScreen. What you want to do is copy the below code of FirstScreen and make three screen dart files.

Replace FirstScreen text whereever you see in SecondScreen and ThirdScreen.

You can also download the source code at the bottom.

first_screen.dart


import 'package:flutter/material.dart';

class FirstScreen extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 150.0, vertical: 10),
        child: Text(
          'First Screen',
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
      ),
    );
  }
}

2. Flutter ListView Navigation + Passing Data

listview navigation with passing data
In this example, while navigating to DetailScreen, we also pass data. How will we do that?

  • In this example, when the tap occurs, we use index of ListView and take Note data from _noteList and pass it to DetailScreen constructor.
  • DetailScreen(note: _noteList[index]) :
  • //_noteList store Note Items.
    final List<Note> _noteList = [
        Note(
          title: 'Note Title 1',
          content: 'Note Content 1',
        ),
        Note(
          title: 'Note Title 2',
          content: 'Note Content 2',
        ),
        Note(
          title: 'Note Title 3',
          content: 'Note Content 3',
        )
      ];
    ...
    ..
    .
    ListView.builder(
              itemCount: _noteList.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(
                    _noteList[index].title,
                  ),
                  subtitle: Text(
                    _noteList[index].content,
                  ),
                  onTap: () {
    //Navigator pushes the DetailScreen and Passes the note data through constructor.
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => DetailScreen(note: _noteList[index]),
                      ),
                    );
                  },
                );
              }),
    
    
  • How to receive this data in DetailScreen?
  • 
    class DetailScreen extends StatelessWidget {
      final Note note;
      const DetailScreen({required this.note});
    
    
    

Let’s create the complete project… So make 3 dart Files.

  1. note.dart
  2. main.dart
  3. detail_screen.dart

note.dart


class Note {
  final String title;
  final String content;

  Note({required this.title, required this.content});
}


main.dart


import 'package:flutter/material.dart';
import 'detail_screen.dart';
import 'note.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ListView Navigation + Passing Data',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ListScreen(),
    );
  }
}

class ListScreen extends StatelessWidget 
{

 final List<Note> _noteList = [
    Note(
      title: 'Note Title 1',
      content: 'Note Content 1',
    ),
    Note(
      title: 'Note Title 2',
      content: 'Note Content 2',
    ),
    Note(
      title: 'Note Title 3',
      content: 'Note Content 3',
    )
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListView Navigation + Passing Data'),
      ),
      body: ListView.builder(
          itemCount: _noteList.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(
                _noteList[index].title,
              ),
              subtitle: Text(
                _noteList[index].content,
              ),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => DetailScreen(note: _noteList[index]),
                  ),
                );
              },
            );
          }),
    );
  }
}


detail_screen.dart



import 'package:flutter/material.dart';

import 'note.dart';

class DetailScreen extends StatelessWidget {
  final Note note;
  const DetailScreen({required this.note});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Detail Screen'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(

            children: [
              Text(
                note.title,
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              ),
              Text(note.content),
            ],
          ),
        ),
      ),
    );
  }
}


3.ListView Navigation – Passing Data Through RouteSettings

listview data passing routesettings
Just like constructor, you can also use RouteSettings to pass data. Just provide your data as value of arguments property.

 final List<Note> _noteList = [
    Note(
      title: 'Note Title 1',
      content: 'Note Content 1',
    ),
    Note(
      title: 'Note Title 2',
      content: 'Note Content 2',
    ),
    Note(
      title: 'Note Title 3',
      content: 'Note Content 3',
    )
  ];
.....
...
..
.
ListTile(
              title: Text(
                _noteList[index].title,
              ),
              subtitle: Text(
                _noteList[index].content,
              ),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => DetailScreen(),
                    settings: RouteSettings(arguments: _noteList[index]),
                  ),
                );
              },
            )

Okay. How to get this data from DetailScreen?

  • Add below code inside build() method of DetailScreen.

final note = ModalRoute.of(context)!.settings.arguments as Note;


Exclamation mark – for null safety. If you are not using null safety, remove it.

note.dart


class Note {
  final String title;
  final String content;

  Note({required this.title, required this.content});
}


main.dart


import 'package:flutter/material.dart';

import 'detail_screen.dart';
import 'note.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter ListView Navigation - Passing Data',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ListScreen(),
    );
  }
}

class ListScreen extends StatelessWidget {
  ListScreen({Key? key}) : super(key: key);

  final List<Note> _noteList = [
    Note(
      title: 'Note Title 1',
      content: 'Note Content 1',
    ),
    Note(
      title: 'Note Title 2',
      content: 'Note Content 2',
    ),
    Note(
      title: 'Note Title 3',
      content: 'Note Content 3',
    )
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListView - Passing Data(RouteSettings)'),
      ),
      body: ListView.builder(
          itemCount: _noteList.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(
                _noteList[index].title,
              ),
              subtitle: Text(
                _noteList[index].content,
              ),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => DetailScreen(),
                    settings: RouteSettings(arguments: _noteList[index]),
                  ),
                );
              },
            );
          }),
    );
  }
}

detail_screen.dart


import 'package:flutter/material.dart';

import 'note.dart';

class DetailScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final note = ModalRoute.of(context)!.settings.arguments as Note;

    return Scaffold(
      appBar: AppBar(
        title: Text('Detail Screen(RouteSettings)'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(
                note.title,
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              ),
              Text(note.content),
            ],
          ),
        ),
      ),
    );
  }
}



4.ListView Navigation To A Statefulwidget With Data + Hero Animation

listview navigation passing data to statefulwidget
In this example, When the ListTile tapped, will move to a DetailScreen which extends StatefulWidget and also displays simple Hero animation.

  • Hero tag value must be unique and you need to specify the same tag value in DetailScreen.
ListTile(
              leading: Hero(
//unique tag - image name
                tag: note.image,
                child: CircleAvatar(
                  backgroundImage: Image.asset('assets/${note.image}').image,
                ),
              ),
              title: Text(
                _noteList[index].title,
              ),
              subtitle: Text(
                _noteList[index].content,
              ),
              onTap: () {
//Navigator pushes the DetailScreen with note data.
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => DetailScreen(_noteList[index]),
                  ),
                );
              },
            )

How to access this data in DetailScreen build method?

  • Inside build() method, you can use widget with field name.
  • Here, final note = widget.note.

class DetailScreen extends StatefulWidget {
  final Note note;

  DetailScreen(this.note);

  @override
  _DetailScreenState createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  @override
  Widget build(BuildContext context) {
//widget.field name 
    final note = widget.note;


Let’s create the whole project. Source code of note.dart file is already given in above example.

Before that, you need to create assets directory to store image files. You can use your own image files or download our source code and use it . Also specify it in pubspec.yaml file.

main.dart


import 'package:flutter/material.dart';

import 'detail_screen.dart';
import 'note.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter ListView Navigation - Passing Data With Hero Animation',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ListScreen(),
    );
  }
}

class ListScreen extends StatelessWidget {
  ListScreen({Key? key}) : super(key: key);

  final List<Note> _noteList = [
    Note(
      title: 'Note Title 1',
      content: 'Note Content 1',
      image: 'nature.jpg',
    ),
    Note(
      title: 'Note Title 2',
      content: 'Note Content 2',
      image: 'island.jpg',
    ),
    Note(
      title: 'Note Title 3',
      content: 'Note Content 3',
      image: 'stones.jpg',
    )
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListView - Passing Data To Stateful Widget'),
      ),
      body: ListView.builder(
          itemCount: _noteList.length,
          itemBuilder: (context, index) {
            final note = _noteList[index];
            return ListTile(
              leading: Hero(
                tag: note.image,
                child: CircleAvatar(
                  backgroundImage: Image.asset('assets/${note.image}').image,
                ),
              ),
              title: Text(
                _noteList[index].title,
              ),
              subtitle: Text(
                _noteList[index].content,
              ),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => DetailScreen(_noteList[index]),
                  ),
                );
              },
            );
          }),
    );
  }
}


detail_screen.dart


import 'package:flutter/material.dart';

import 'note.dart';

class DetailScreen extends StatefulWidget {
  final Note note;

  DetailScreen(this.note);

  @override
  _DetailScreenState createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  @override
  Widget build(BuildContext context) {
    final note = widget.note;

    return Scaffold(
      appBar: AppBar(
        title: Text('Detail Screen(RouteSettings)'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Hero(
                tag: note.image,
                child: Image.asset('assets/${note.image}'),
              ),
              SizedBox(height: 8),
              Text(
                note.title,
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              ),
              Text(note.content),
            ],
          ),
        ),
      ),
    );
  }
}


Download Source Code

If you like this post, please share it with your family and friends.

Please disable your adblocker or whitelist this site!