![](/img/trans.png)
[英]Flutter - How to show data from 2 objects in single Json file based on the same value
[英]How to show data from 2nd JSON based on the same value of String
我有 2 JSON 文件:
国家.json
[
{
"countryName": "United States",
"countryContinent": "North America"
},
{
"countryName": "Germany",
"countryContinent": "Europe"
},
{
"countryName": "United Kingdom",
"countryContinent": "Europe"
}
]
大陆.json
[
{
"continentName": "North America",
"continentCountry": [
"Canada",
"Mexico",
"Cuba"
],
"continentArea": 24790000,
"continentFlag": [
"https://www.countryflags.io/ca/shiny/64.png",
"https://www.countryflags.io/mx/shiny/64.png",
"https://www.countryflags.io/cu/shiny/64.png"
]
},
{
"continentName": "Europe",
"continentCountry": [
"Denmark",
"Finland",
"France"
],
"continentArea": 10180000,
"continentFlag": [
"https://www.countryflags.io/dk/shiny/64.png",
"https://www.countryflags.io/fi/shiny/64.png",
"https://www.countryflags.io/fr/shiny/64.png"
]
}
]
我想建立一个基于 country.json 的列表,然后对于countryContinent
的每个值 == continentName
的值 => 显示来自 continent.json 的值continentCountry
的数据,就像这样
所以请帮助我,这是主文件:
import 'package:ask/model/continent_model.dart';
import 'package:ask/model/country_model.dart';
import 'package:ask/services/continent_services.dart';
import 'package:ask/services/country_service.dart';
import 'package:flutter/material.dart';
class Demo2 extends StatefulWidget {
Demo2() : super();
@override
_Demo2State createState() => _Demo2State();
}
class _Demo2State extends State<Demo2> {
List<Country> _country = [];
List<Continent> _continent = [];
@override
void initState() {
super.initState();
CountryServices.getCountry().then((countries) {
setState(() {
_country = countries;
});
});
ContinentServices.getContinent().then((continents) {
setState(() {
_continent = continents;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo 2')),
body: Column(
children: <Widget>[
for (Country country in _country)
Row(
children: <Widget>[
Expanded(child: Text(country.countryName)),
Expanded(child: Text(country.countryContinent)),
Expanded(child: Text('')), // How to show data of continentCountry
],
)
],
));
}
}
为了避免创建另一个帖子,我扩展了以下问题:在 continent.json 中,有更多关于continentCountry
("Greenland"; "Panama"; "Jamaica") 的数据与continentName
("North America") 的值匹配,如下所示:
continent.json(编辑2)
[
{
"continentName": "North America",
"continentArea": "Area1",
"continentCountry": [
"Canada",
"Mexico",
"Cuba"
],
"continentFlag": [
"https://www.countryflags.io/ca/shiny/64.png",
"https://www.countryflags.io/mx/shiny/64.png",
"https://www.countryflags.io/cu/shiny/64.png"
]
},
{
"continentName": "North America",
"continentArea": "Area2",
"continentCountry": [
"Greenland",
"Panama",
"Jamaica"
],
"continentFlag": [
"https://www.countryflags.io/gl/shiny/64.png",
"https://www.countryflags.io/pa/shiny/64.png",
"https://www.countryflags.io/jm/shiny/64.png"
]
},
{
"continentName": "Europe",
"continentArea": "Area3",
"continentCountry": [
"Denmark",
"Finland",
"France"
],
"continentFlag": [
"https://www.countryflags.io/dk/shiny/64.png",
"https://www.countryflags.io/fi/shiny/64.png",
"https://www.countryflags.io/fr/shiny/64.png"
]
},
{
"continentName": "Asia",
"continentArea": "Area4",
"continentCountry": [
"Japan"
],
"continentFlag": [
"https://www.countryflags.io/jp/shiny/64.png"
]
}
]
所以我想显示“北美”的所有continentCountry
国家,如下所示:
请帮忙
您可以在单独的 function 中遍历字符串List<String>
,例如List<Text> getSameContinentCountries
。
国家
class Country {
String countryName;
String countryContinent;
Country({this.countryName, this.countryContinent});
factory Country.fromJson(Map<String, dynamic> json) {
return Country(
countryName: json['countryName'],
countryContinent: json['countryContinent'],
);
}
}
大陆
class Continent {
String continentName;
List<String> continentCountry;
Continent({this.continentName, this.continentCountry});
factory Continent.fromJson(Map<String, dynamic> json) {
return Continent(
continentName: json['continentName'],
continentCountry: json['continentCountry'],
);
}
}
您现在可以在 initState 中生成List<Country> _country
和List<Continent> _continent
:
// TODO generate Lists
for (Map<String, dynamic> _json in continentListResponse) {
continent2 = Continent.fromJson(_json);
this._continent.add(continent2);
}
for (Map<String, dynamic> _json in countryListResponse) {
country2 = Country.fromJson(_json);
this._country.add(country2);
}
纯文本
List<Text> getSameContinentCountries({@required String countryContinent}) {
int continentIndex = this
._continent
.indexWhere((continent) => continent.continentName == countryContinent);
List<String> _cC = this._continent[continentIndex].continentCountry;
List<Text> wrapText = [Text('no Countries found')];
if (_cC.length > 0) {
wrapText = [];
for (String country in _cC) {
wrapText.add(Text(country));
}
}
return wrapText;
}
所有小部件
List<Widget> getSameContinentCountries({@required String countryContinent}) {
// returns a List of any Widget, many combinations possible
// such as chips, cards etc.
int continentIndex = this
._continent
.indexWhere((continent) => continent.continentName == countryContinent);
List<String> _cC = this._continent[continentIndex].continentCountry;
List<Widget> wrapText = [Text('no Countries found')];
if (_cC.length > 0) {
wrapText = [];
for (String country in _cC) {
// you may want to use Padding
wrapText.add(Padding(
padding: const EdgeInsets.symmetric(horizontal: 2),
child: Text(country),
));
// simple | divider with Text widget
wrapText.add(Padding(
padding: const EdgeInsets.symmetric(horizontal: 2),
child: Text('|'),
));
// or use the VerticalDivider which needs a parent with height
wrapText.add(
Container(
height: 15,
child: VerticalDivider(
color: Colors.red,
width: 4,
thickness: 2,
)),
);
// or use any other widget, eg. chips
wrapText.add(Chip(
label: Text(country),
));
}
}
// remove the last "divider"
wrapText.removeLast();
return wrapText;
}
在这里,我建议您使用Wrap
Widget。
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo 2')),
body: Column(
children: <Widget>[
for (Country country in _country)
Row(
children: <Widget>[
Expanded(child: Text(country.countryName)),
Expanded(child: Text(country.countryContinent)),
Expanded(
child: Wrap(
children: getSameContinentCountries(
countryContinent: country.countryContinent)),
),
],
)
],
));
}
我还不能评论另一个答案,所以我必须在我的答案中包含这个简短的信息。
要使用图像,只需返回一个 Image 小部件,您可能希望将它包装在一个Sized Box
或一个Button
/ GestureDetctor
中用于点击事件。
List<Widget> getFlags({@required String countryContinent}) {
// returns a List of any Widget, many combinations possible
// such as chips, cards, images, buttons etc.
int continentIndex = this
._continent
.indexWhere((continent) => continent.continentName == countryContinent);
List<String> _cF = this._continent[continentIndex].continentFlag;
List<Widget> wrapWidget = [Text('no Countries found')];
if (_cF.length > 0) {
wrapWidget = [];
for (String flag in _cF) {
// add the Flags
wrapWidget.add(Image.network(flag));
}
}
return wrapWidget;
}
结果:
要访问具有相同continentName
的所有标志,您必须提取匹配的元素,然后遍历新的List<Continent>
。 像这样更改getFlags
function 的代码:
List<Widget> getFlags({@required String countryContinent}) {
// returns a List of any Widget, many combinations possible
// such as chips, cards, images, buttons etc.
//! UPDATE
List<Continent> sameContient = this
._continent
.where((continent) => continent.continentName == countryContinent)
.toList();
List<String> _cF = [];
for (Continent sc in sameContient) {
for (String flag in sc.continentFlag) {
_cF.add(flag);
}
}
List<Widget> wrapWidget = [Text('no Countries found')];
if (_cF.length > 0) {
wrapWidget = [];
for (String flag in _cF) {
// add the Flags
wrapWidget.add(
Image.network(flag, height: 16, width: 25, fit: BoxFit.contain));
}
}
return wrapWidget;
}
Expanded(
child: MyCountries(
continent: List<Continent>.from(_continent)..retainWhere((continent) =>
continent.continentName == country.countryContinent)
),
我创建了一个接收列表的小部件 MyCountries,首先我创建了该列表的副本 (List.from) 以避免更改原始列表 _continent。 RetainWhere 只保留满足条件的元素。 您只想保留 countryContinent == continentName 所在的大陆
continent.continentName == country.countryContinent
在我的国家小部件中
class MyCountries extends StatelessWidget{
final String countries;
MyCountries({List<Continent> continent}) :
this.countries = continent.reduce((prev, curr) =>
prev..continentCountry.addAll(curr.continentCountry)).continentCountry.join(' | ');
@override
Widget build(BuildContext context) {
return Text(countries);
}
}
它获取大陆列表并将其缩减为单个大陆 object 以及包含所有国家/地区的大陆国家/地区列表,然后只需应用continentCountry.join(' | ')
加入该列表的所有字符串并创建您将使用的国家/地区字符串在文本小部件中
更新
根据我对您的评论的理解,应该只有一个 countryContinent == continentName 的值,我认为可能会有更多(我的坏),所以也许您应该像这样更改它
Expanded(
child: MyArea(
continent: _continent.firstWhere((continent) => continent.continentName == country.countryContinent)
//This should return the first ocurrence, only one continent object
),
class MyArea extends StatelessWidget{
final String area;
MyArea({Continent continent}) :
this.area = continent.continentArea.toString(); //You need to give a string to the Text widget anyway
@override
Widget build(BuildContext context) {
return Text(area);
}
}
我想 List 是标志的 url 列表
Expanded(
child: MyFlags(
continent: _continent.firstWhere((continent) => continent.continentName == country.countryContinent)
//This should return the first ocurrence, only one continent object
),
class MyFlags extends StatelessWidget{
final List<String> flags;
MyFlags ({Continent continent}) :
this.flags= continent.continentFlag;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, //or try other alignments or using Spacer() between widget in children
children: [
for(String flag in flags)
Image.network(flag, height: 16, width: 25, fit: BoxFit.contain)
//A flag is wider thatn taller, but you could try other sizes if you want
]
);
}
}
更新 2
Expanded(
child: MyFlags(
continent: List<Continent>.from(_continent)..retainWhere((continent) =>
continent.continentName == country.countryContinent)
),
class MyFlags extends StatelessWidget{
final List<String> flags;
final List<String> countries;
MyFlags ({List<Continent> continent}) :
this.flags = continents.expand<String>((continent) => continent.continentFlag).toList(),
this.countries = continents.expand<String>((continent) => continent.continentCountry).toList(),
assert(flags.length == countries.length); //They should have the same length
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, //or try other alignments or using Spacer() between widget in children
children: [
for(int i = 0; i < flags.length; i++)
Column(
children: [
Image.network(flags[i], height: 16, width: 25, fit: BoxFit.contain),
Text(countries[i])
]
)
]
);
}
}
更新 3
Expanded(
child: MyFlags(
continent: List<Continent>.from(_continent)..retainWhere((continent) =>
continent.continentName == country.countryContinent)
),
class MyFlags extends StatelessWidget{
final List<Continent> continent;
MyFlags({this.continent});
@override
Widget build(BuildContext context) {
return Column(
children: [
for(int i = 0; i < continent.length; i++)
Row(
children: [
Text(continent[i].continentArea.toString()), // or 'Area ${i+1}' if you want to show Area 1, Area 2, etc
for(String flag in continent[i].continentFlag)
Image.network(flags[i], height: 16, width: 25, fit: BoxFit.contain),
]
)
]
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.