从一个列表制作多个小部件

Making multiple Widgets from one list

我目前正在学习使用 Dart 在 Flutter 中编写移动应用程序,最近我想尝试构建一个应用程序,您可以在其中保留您仍想观看的电影并获取有关它们的一些基本信息。现在这只适合我,训练以了解 flutter 的基本概念,我想问一下如何从一个列表中制作多个小部件。我会向您展示我的代码,然后对其进行详细说明。

import 'package:flutter/material.dart';

class MovieList {
  String name;
  String url;
  String description;
  String actors;
  int id;

  MovieList(this.name, this.url, this.description, this.actors, this.id);

  var movies = [
    {
      "21",
      "assets/images/21_movie.jpeg",
      "randomDescriptionfor21",
      "idkwhichactors.1",
      1
    },
    {
      "Dirty Dancing",
      "assets/images/dirty_dancing_movie.jpeg",
      "randomDescriptionforDirtyDancing",
      "idkwhichactors.2",
      2
    },
    {
      "Endless love",
      "assets/images/endless_love_movie.jpeg",
      "randomDescriptionforEndlesslove",
      "idkwhichactors.3",
      3
    },
    {
      "Gut gegen Nordwind",
      "assets/images/gut_gegen_nordwind_movie.jpeg",
      "randomDescriptionforNordwind",
      "idkwhichactors.4",
      4
    },
    {
      "Illuminati",
      "assets/images/illuminati_movie.jpeg",
      "randomDescriptionforIlluminati",
      "idkwhichactors.5",
      5
    },
    {
      "Bridget Jones",
      "assets/images/jones_movie.jpeg",
      "randomDescriptionforBridgetJones",
      "idkwhichactors.6",
      6
    },
    {
      "Kevin allein Zuhaus",
      "assets/images/kevin_allein_zuhaus_movie.jpeg",
      "randomDescriptionforKevin",
      "idkwhichactors.7",
      7
    },
    {
      "Little Woman",
      "assets/images/little_woman_movie.jpeg",
      "randomDescriptionforLittleWoman",
      "idkwhichactors.8",
      8
    },
    {
      "Liebe braucht keine Ferien",
      "assets/images/love_movie.jpeg",
      "randomDescriptionforLiebeundFerien",
      "idkwhichactors.9",
      9
    },
    {
      "Marvel-Filme",
      "assets/images/marvel_movie.jpeg",
      "randomDescriptionforMarvel",
      "idkwhichactors.10",
      10
    },
    {
      "Oceans 12",
      "assets/images/oceans_12_movie.jpeg",
      "randomDescriptionforOceans12",
      "idkwhichactors.11",
      11
    },
    {
      "Pirates of the Carribean",
      "assets/images/pirates_carribean_movie.jpeg",
      "randomDescriptionforPiraten",
      "idkwhichactors.12",
      12
    },
    {
      "Romeo und Julia",
      "assets/images/romeo_and_julia_movie.jpeg",
      "randomDescriptionforRomeoxJulia",
      "idkwhichactors.13",
      13
    },
    {
      "A star is born",
      "assets/images/star_movie.jpeg",
      "randomDescriptionforStar",
      "idkwhichactors.14",
      14
    },
    {
      "Die Entdeckung der Unendlichkeit",
      "assets/images/stephen_hawking_movie.jpeg",
      "randomDescriptionforStephen",
      "idkwhichactors.15",
      15
    },
    {
      "Frühstück bei Tiffany",
      "assets/images/tiffany_movie.jpeg",
      "randomDescriptionforTIffany",
      "idkwhichactors.16",
      16
    }
  ];
}

因此,如您所见,我定义了一个 class、MovieList,我在其中定义了某些变量(名称、url、描述、演员、id)。现在在那些我定义一个包含多部电影的列表的初始化下,具有所有这些属性。

  1. 问题:如何使用列表创建 MovieList 的多个对象以及如何实现循环(或者其他我知道如何完成)来显示多个小部件,匹配我的电影在“电影”列表中定义?

  2. 问题:这是否是正确的方法,是否可行?就像我说的,我几乎是从 dart 和 flutter 开始的,所以我真的需要你的帮助。

提前致谢:)

所以非常感谢你真的帮了我很多。现在我想做我的卡片小部件,这基本上就是我更改代码的方式: 1:

``
import 'package:flutter/material.dart';
import './header.dart';
import './image_widget.dart';
import './movies_to_watch.dart';

var movies = [
  {
    'title': '21',
    'bannerPath': 'assets/images/21_movie.jpeg',
    'description': 'randomDescriptionforPirates',
    'actors': [
      'some actor',
    ]
  },
  {
    'title': 'Dirty Dancing',
    'bannerPath': 'assets/images/dirty_dancing_movie.jpeg',
    'description': 'randomDescriptionforPirates',
    'actors': [
      'some actor',
    ]
  },
  {
    'title': 'Endless Love',
    'bannerPath': 'assets/images/endless_love_movie.jpeg',
    'description': 'randomDescriptionforPirates',
    'actors': [
      'some actor',
    ]
  },
  {
    'title': 'Gut gegen Nordwind',
    'bannerPath': 'assets/images/gut_gegen_nordwind_movie.jpeg',
    'description': 'randomDescriptionforPirates',
    'actors': [
      'some actor',
    ]
  },
  {
    'title': 'Illuminati',
    'bannerPath': 'assets/images/illuminati_movie.jpeg',
    'description': 'randomDescriptionforPirates',
    'actors': [
      'some actor',
    ]
  },
  {
    'title': 'Bridget Jones',
    'bannerPath': 'assets/images/jones_movie.jpeg',
    'description': 'randomDescriptionforPirates',
    'actors': [
      'some actor',
    ]
  },
  {
    'title': 'Kevin allein zuhaus',
    'bannerPath': 'assets/images/kevin_allein_zuhaus_movie.jpeg',
    'description': 'randomDescriptionforPirates',
    'actors': [
      'some actor',
    ],
  },
];

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

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: EdgeInsets.only(bottom: 20.0),
            child: HeaderWidget(),
          ),
          Padding(
            padding: EdgeInsets.only(right: 20.0, left: 20.0),
            child: FilmstoWatch(),
          ),
          Padding(
            padding: EdgeInsets.only(right: 20.0, left: 20.0),
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Row(
                children: [
                  for (var movie in movies)
                    MovieWidget(model: MovieModel.fromJson(movie)),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}
``

和 2:

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

class MyClass {
  // here I am generating fake movies but you should use the data that you already have
  List<Map<String, dynamic>> movies = List.generate(
      15,
      (index) => {
            'title': 'fake title $index',
            'actors': ['fake actor $index'],
            'bannerPath': 'some/fake/path/$index',
            'description': 'some fake description $index',
          });

  List<MovieModel> get models =>
      movies.map((movie) => MovieModel.fromJson(movie)).toList();

  List<Widget> get widgets =>
      models.map((model) => MovieWidget(model: model)).toList();
}

class MovieModel {
  MovieModel({
    required this.title,
    required this.actors,
    required this.bannerPath,
    required this.description,
  });

  factory MovieModel.fromJson(Map<String, dynamic> json) {
    return MovieModel(
      title: json['title'],
      actors: json['actors'],
      bannerPath: json['bannerPath'],
      description: json['description'],
    );
  }

  String title;
  String bannerPath;
  String description;
  List<String> actors;
}

class MovieWidget extends StatelessWidget {
  const MovieWidget(
      {required this.model}); // if you decide to not make a model class, you would pass each value individually

  final MovieModel model;

  @override
  Widget build(BuildContext context) {
    // obviously this can be any widget you want
    return SingleChildScrollView(
      child: Card(
        shape:
            RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
        elevation: 10.0,
        margin: const EdgeInsets.all(10.0),
        child: Column(
          children: [
            Text(model.title),
            Container(
              height: 200,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(10.0),
                image: DecorationImage(
                  image: AssetImage(model.bannerPath),
                ),
              ),
            ),
            Text(model.description),
            if (model.actors.isNotEmpty) Text(model.actors.first),
          ],
        ),
      ),
    );
  }
}
``

如果我运行这个我会抛出这个错误:

https://drive.google.com/file/d/1zbmsOq3lQIPUIZ92mvrg4sCcT21W8cc4/view?usp=sharing

当我将 model.bannerPath 替换为应该插入的实际字符串时,它起作用了。再次感谢您的帮助!

老实说,我不是集合的忠实粉丝,也不知道你为什么决定使用它们,所以我将你的集合更改为地图,我还删除了它们的整数,因为我不知道为什么它会有用。正如我所说,这就是我的编码方式,我希望您可以决定是否要保留这些集合

var movies = [
  ...
  {
    'title': 'Pirates of the Carribean',
    'banner': 'assets/images/pirates_carribean_movie.jpeg',
    'description': 'randomDescriptionforPiraten',
    'actors': ['some actor'],
  },
  ...
];

我还建议您制作一个 MovieModel class 可以以类型安全的方式存储这些值

class MovieModel {
  String title;
  String bannerPath;
  String description;
  List<String> actors;
}

那么你应该做一些可以显示你想要的信息的小部件

class MovieWidget extends StatelessWidget {
  MovieWidget({required this.model}); // if you decide to not make a model class, you would pass each value individually

  final MovieModel model;

  @override
  Widget build(BuildContext context) {
    // obviously this can be any widget you want
    return Column(
      children: [
        Text(model.title),
        Text(model.banner),
        Text(model.description),
        Text(model.actors.first),
      ],
    );
  }
}

最后要把你的电影列表变成一个小部件列表,首先你需要把它变成一个模型列表

final List<MovieModel> models = movies.map((movie) => MovieModel(title: movie['title'], banner: movie['banner'], description: movie['description'], actors: movie['actors']));

然后您可以对小部件执行相同的操作:

List<Widget> widgets = models.map((model) => MovieWidget(model: model));

编辑:

关于您对使用老电影变量的评论。

例如,如果您想将所有这些小部件添加到列中:

return Column(
  children: [
    for (var movie in movies)
      MovieWidget(model: MovieModel.fromJson(movie)),
  ],
);

显然在上面的例子中,如果你想添加填充,你只需要用填充包围 MovieWidget