4

I am using PageView builder in my flutter app to display scrollable cards. For that I have first created a widget _buildCarousel and widget _buildCarouselItem to display it using my defined by defined widget for card. I have also defined a List of Maps (eventsData) for the events' data.

  Widget _buildCarousel(BuildContext context) {
    List<Map> EventsData = [
      {
        "title": "Event ABC",
        "subTitle": "Organised by XYZ",
        "desc": "Event description.",
        "date": "13th Jan, 2022",
        "time": "4:00 pm",
        "lastDate": "11th Jan, 2022"
      },
      {
        "title": "Event MNT",
        "subTitle": "Organised by XYZ",
        "desc": "Event description.",
        "date": "13th Jan, 2022",
        "time": "4:00 pm",
        "lastDate": "11th Jan, 2022"
      },
      {
        "title": "Event WOQ",
        "subTitle": "Organised by STU",
        "desc": "Event description." ,
        "date": "13th Jan, 2022",
        "time": "4:00 pm",
        "lastDate": "11th Jan, 2022"
      }
    ];
    return SizedBox(
      height: 500.0,
      child: PageView.builder(
        itemCount: EventsData.length,
        controller: PageController(viewportFraction: 1),
        itemBuilder: (BuildContext context, int itemIndex) {
          return _buildCarouselItem(context);
        },
      ),
    );
  }

  Widget _buildCarouselItem(BuildContext context) {
    return Padding(
        padding: EdgeInsets.symmetric(horizontal: 4.0), child: EventCard());
  }

Here EventCard is my defined widget for a Card. Code for EventCard widget is:

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

  @override
  Widget build(BuildContext context) {

    return Card(
      elevation: 10,
      shadowColor: Colors.black,
      margin: EdgeInsets.all(25.0),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(16.0),
      ),
      color: const Color(0xffB7AC44),
      child: SizedBox(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              SizedBox(
                height: 10,
              ),
              Text(
                'Title',
                style: TextStyle(
                    fontSize: 22,
                    color: Colors.white,
                    fontWeight: FontWeight.w900,
                    fontFamily: 'Montserrat'),
              ),
              SizedBox(
                height: 10,
              ),
              Text(
                'Sub Title',
                style: TextStyle(
                    fontSize: 16,
                    color: Colors.black,
                    fontWeight: FontWeight.w700,
                    fontFamily: 'Montserrat'),
              ),
              SizedBox(
                height: 10,
              ),
              SizedBox(
                height: 100,
                child: Text(
                  'Description',
                  maxLines: 6,
                  overflow: TextOverflow.ellipsis,
                  style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400),
                ),
              ),
              SizedBox(
                height: 20,
              ),
              Spacer(),
              Column(
                children: [
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      'Date: 12 May, 2022',
                      style: TextStyle(
                          fontSize: 14,
                          color: Colors.black,
                          fontWeight: FontWeight.w700,
                          fontFamily: 'Montserrat'),
                    ),
                  ),
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      'Time: 5:00 pm',
                      style: TextStyle(
                          fontSize: 14,
                          color: Colors.black,
                          fontWeight: FontWeight.w700,
                          fontFamily: 'Montserrat'),
                    ),
                  ),
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      'Last date to register: 31 May, 2022',
                      style: TextStyle(
                          fontSize: 14,
                          color: Colors.black,
                          fontWeight: FontWeight.w700,
                          fontFamily: 'Montserrat'),
                    ),
                  ),
                ],
              ),
              SizedBox(
                height: 20,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Here's the output:

enter image description here

As you can see, here the values for the different text widgets in Card are static. But I want these values to be based on the items of the List EventsData that I have defined earlier in _buidCarousel. I am unable to figure out how should I do that. Where should exactly I define this eventsData list and how can I take these values for my card widget.

enggPS
  • 686
  • 1
  • 7
  • 23

2 Answers2

6

replace this '''

List<Map> EventsData = [
  {
    "title": "Event ABC",
    "subTitle": "Organised by XYZ",
    "desc": "Event description.",
    "date": "13th Jan, 2022",
    "time": "4:00 pm",
    "lastDate": "11th Jan, 2022"
  },
  {
    "title": "Event MNT",
    "subTitle": "Organised by XYZ",
    "desc": "Event description.",
    "date": "13th Jan, 2022",
    "time": "4:00 pm",
    "lastDate": "11th Jan, 2022"
  },
  {
    "title": "Event WOQ",
    "subTitle": "Organised by STU",
    "desc": "Event description." ,
    "date": "13th Jan, 2022",
    "time": "4:00 pm",
    "lastDate": "11th Jan, 2022"
  }
];

''' With this '''

class Model {
  String title;
  String subTitle;
  String desc;
  String date;
  String time;
  String lastDate;
  Model({
    required this.title,
    required this.subTitle,
    required this.desc,
    required this.date,
    required this.time,
    required this.lastDate,
  });
}

Widget _buildCarousel(BuildContext context) {
  List<Model> eventsData = [
    Model(
      title: "Event ABC",
      subTitle: "Organised by XYZ",
      desc: "Event description.",
      date: "13th Jan, 2022",
      time: "4:00 pm",
      lastDate: "11th Jan, 2022",
    ),
    Model(
      title: "Event",
      subTitle: "Organised",
      desc: "Event description.",
      date: "13th Jan, 2022",
      time: "5:00 pm",
      lastDate: "2th Jan, 20203",
    ),
    Model(
      title: "Event WOQ",
      subTitle: "Organised by STU",
      desc: "Event description.",
      date: "13th Jan, 2022",
      time: "4:00 pm",
      lastDate: "11th Jan, 2022",
    ),
  ];

  return SizedBox(
    height: 500.0,
    child: PageView.builder(
      itemCount: eventsData.length,
      controller: PageController(viewportFraction: 1),
      itemBuilder: (BuildContext context, int itemIndex) {
        return Padding(
            padding: const EdgeInsets.symmetric(horizontal: 4.0),
            child: EventCard(
              model: eventsData[itemIndex],
            ));
      },
    ),
  );
}

'''

and your card resave Model and this model has data ''' class EventCard extends StatelessWidget { const EventCard({ Key? key, required this.model, }) : super(key: key); final Model model;

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 10,
      shadowColor: Colors.black,
      margin: const EdgeInsets.all(25.0),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(16.0),
      ),
      color: const Color(0xffB7AC44),
      child: SizedBox(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              const SizedBox(
                height: 10,
              ),
              Text(
                model.title,
                style: const TextStyle(
                    fontSize: 22,
                    color: Colors.white,
                    fontWeight: FontWeight.w900,
                    fontFamily: 'Montserrat'),
              ),
              const SizedBox(
                height: 10,
              ),
              Text(
                model.subTitle,
                style: const TextStyle(
                    fontSize: 16,
                    color: Colors.black,
                    fontWeight: FontWeight.w700,
                    fontFamily: 'Montserrat'),
              ),
              const SizedBox(
                height: 10,
              ),
              SizedBox(
                height: 100,
                child: Text(
                  model.desc,
                  maxLines: 6,
                  overflow: TextOverflow.ellipsis,
                  style: const TextStyle(
                      fontSize: 14, fontWeight: FontWeight.w400),
                ),
              ),
              const SizedBox(
                height: 20,
              ),
              const Spacer(),
              Column(
                children: [
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      model.date,
                      style: const TextStyle(
                          fontSize: 14,
                          color: Colors.black,
                          fontWeight: FontWeight.w700,
                          fontFamily: 'Montserrat'),
                    ),
                  ),
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      model.time,
                      style: const TextStyle(
                          fontSize: 14,
                          color: Colors.black,
                          fontWeight: FontWeight.w700,
                          fontFamily: 'Montserrat'),
                    ),
                  ),
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      model.lastDate,
                      style: const TextStyle(
                          fontSize: 14,
                          color: Colors.black,
                          fontWeight: FontWeight.w700,
                          fontFamily: 'Montserrat'),
                    ),
                  ),
                ],
              ),
              const SizedBox(
                height: 20,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

'''

2
  1. Add the required parameters as members to your EventCard class like this (this shows only title, but you can add the others as well):
class EventCard extends StatelessWidget {
  final String title;
  1. Modify the constructor to initialize these members:
  EventCard({required this.title, Key? key}) : super(key: key);
  1. Use these members in EventCard class:
Text(
  title, //'Title',
  style: TextStyle(...
  1. In the itemBuilder you can pass the corresponding value directly to the EventCard constructor:
itemBuilder: (BuildContext context, int itemIndex) =>
  Padding(
    padding: EdgeInsets.symmetric(horizontal: 4.0),
    child: EventCard(title: EventsData[itemIndex]["title"] ?? ''),
}
Peter Koltai
  • 8,296
  • 2
  • 10
  • 20
  • As a rule of thumb avoid functions returning widgets, these are handled differently by the framework. Try to return widgets only from build methods, and if you need some customizations, create your own widget class. – Peter Koltai Feb 22 '22 at 16:01
  • Can you more elaborate on the above comment? Also, is it possible to send entire map instead of passing individual keys as you have mentioned? – enggPS Feb 22 '22 at 16:19
  • 1
    For the last comment see this [answer](https://stackoverflow.com/questions/53234825/what-is-the-difference-between-functions-and-classes-to-create-reusable-widgets) and also [this video from Flutter team](https://www.youtube.com/watch?v=IOyq-eTRhvo) which is also linked to the mentioned answer. – Peter Koltai Feb 22 '22 at 16:39
  • Yes, you can send one map (or event better an instance of a class) containing all the data, as the other answer suggests. I just wanted to be simple in the answer. – Peter Koltai Feb 22 '22 at 16:40