Kit Mateyawa
Kit Mateyawa

Reputation: 197

How to navigate to another page using the widgets generated from a 'for loop' in Flutter?

I'm testing out this Flutter project which generates a movie list from a for loop:for (int i = 0; i < 3; i++) {...}. The result of the loop is 3 cards which I'd like to add an onTap function to and navigate to the corresponding page as a result.

Github:https://github.com/devefy/Flutter-Streaming-Service-App-UI/blob/master/lib/main.dart

After the padding on line 222, I added a ListTile() with the onTap:(){} widget. This enabled the tap widget for the bottom half of the card.

// Line 219 to 222
Padding(
padding: EdgeInsets.only(top: 3.0),
child: Text(i == 0 ? "Season 2" : ""),
),// Padding
ListTile(onTap: (){
debugPrint('${[i]} was tapped!');
//Navigator.push(context, route)

My results when tapping the 3 cards.

flutter: [0] was tapped!
flutter: [1] was tapped!
flutter: [2] was tapped!

Where I get lost is how to actually navigate to the detail page of the movie depending on which card I tap on.

Any help is appreciated...Thank You All!!!

Upvotes: 0

Views: 2333

Answers (2)

Kit Mateyawa
Kit Mateyawa

Reputation: 197

Finally found a solution I was happy with. Thanks to flutter_ui_challenge.

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


class YouTubeVideoList extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("YouTube Video List"),
        backgroundColor: Colors.lightBlue,
        elevation: 2,
        actions: <Widget>[
          Container(
            padding: EdgeInsets.all(10),
          )
        ],
      ),
      body: Lists(),
    );
  }
}

class Item {
  final String title;
  final String category;
  final String place;
  final Function onTap;
  final String image;

  Item(
      {this.title,
        this.category,
        this.place,
        this.onTap,
        this.image});
}

class Lists extends StatelessWidget {
  final List<Item> _data = [
    Item(
        onTap: playYoutubeVideo1,
        title: 'Gardens By the Bay',
        category: "Gardens",
        place: "Singapore",
        image: "https://images.pexels.com/photos/672142/pexels-photo-672142.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"),
    Item(
        onTap: playYoutubeVideo2,
        title: 'Singapore Zoo',
        category: "Parks",
        place: "Singapore",
        image: "https://images.pexels.com/photos/1736222/pexels-photo-1736222.jpeg?cs=srgb&dl=adult-adventure-backpacker-1736222.jpg&fm=jpg"),
    Item(
        onTap: playYoutubeVideo3,
        title: 'National Orchid Garden',
        category: "Parks",
        place: "Singapore",
        image: "https://images.pexels.com/photos/62403/pexels-photo-62403.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"),

  ];

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      padding: EdgeInsets.all(6),
      itemCount: _data.length,
      itemBuilder: (BuildContext context, int index) {
        Item item = _data[index];
        return GestureDetector(
          onTap: item.onTap,
          child: Card(
            elevation: 3,
            child: Row(
              children: <Widget>[
                Container(
                  height: 125,
                  width: 110,
                  padding:
                  EdgeInsets.only(left: 0, top: 10, bottom: 70, right: 20),
                  decoration: BoxDecoration(
                      image: DecorationImage(
                          image: NetworkImage(item.image),
                          fit: BoxFit.cover)),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(
                        item.title,
                        style: TextStyle(
                            color: Colors.deepOrange,
                            fontWeight: FontWeight.w700,
                            fontSize: 15),
                      ),
                      Text(
                        item.category,
                        style: TextStyle(fontSize: 12, color: Colors.black87),
                      ),
                      Text(
                        item.place,
                        style: TextStyle(fontSize: 10, color: Colors.black87),
                      ),
                      SizedBox(
                        height: 10,
                      ),

                    ],
                  ),
                )
              ],
            ),
          ),
        );
      },
    );
  }

  var youtube = new FlutterYoutube();

 static playYoutubeVideo1() {
    FlutterYoutube.playYoutubeVideoByUrl(
      apiKey: "YOUR_API_KEY",
      videoUrl: "YOUTUBE_VIDEO_URL",
    );
  }

  static playYoutubeVideo2() {
    FlutterYoutube.playYoutubeVideoByUrl(
      apiKey: "YOUR_API_KEY",
      videoUrl: "YOUTUBE_VIDEO_URL",
    );
  }

  static playYoutubeVideo3() {
    FlutterYoutube.playYoutubeVideoByUrl(
      apiKey: "YOUR_API_KEY",
      videoUrl: "YOUTUBE_VIDEO_URL",
    );
  }
}


Upvotes: 0

Anthony Sette
Anthony Sette

Reputation: 837

The best practice for something like this would be to create 2 pages, a movie list, and a details page.

The movie list will loop through all of the movies, then the on tap would point to the details page. The key here is that you can pass data to the details page when navigating. Whether that be an id or slug for the movie allowing you to fetch specific data or just an index to a list for a simpler example.

Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(todo: todos[index]),),);

Here is an example regarding a todo list and a details screen. I would try running this so you can understand further what I mean.

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),
            // When a user taps the ListTile, navigate to the DetailScreen.
            // Notice that you're not only creating a DetailScreen, you're
            // also passing the current todo through to it.
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(todo: todos[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  // Declare a field that holds the Todo.
  final Todo todo;

  // In the constructor, require a Todo.
  DetailScreen({Key key, @required this.todo}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // Use the Todo to create the UI.
    return Scaffold(
      appBar: AppBar(
        title: Text(todo.title),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text(todo.description),
      ),
    );
  }
}

Here is the app running.

To Do Example

Let me know if you have any questions!

Upvotes: 1

Related Questions