我有一个这样的页面:
Axis.vertical
Axis.horizontal
,itemCount = 3
。为避免错误,我为此设置了height:50
的{{1}} width:100
但是,我想找到一种使其在所有屏幕上都能正常显示的方法,特别是在第二个ListView中:
Container
(1:1:1),并且它适合屏幕的右侧,无法滚动。 Expanded
中的Width
将基于Container
自动调整大小。 Expanded flex
中的fontSize
和Text
中的Height
将基于Container
自动调整大小 所以请帮我,这是JSON文件
maxLine
这是主文件
[
{
"id": 1,
"continent": "North America",
"countries": [
{
"name": "United States",
"capital": "Washington, D.C.",
"language": ["English"]
},
{
"country": "Canada",
"capital": "Ottawa",
"language": ["English", "French"]
},
{
"country": "Mexico",
"capital": "Mexico City",
"language": ["Spanish"]
}
]
},
{
"id": 2,
"continent": "Europe",
"countries": [
{
"country": "Germany",
"capital": "Berlin",
"language": ["German"]
},
{
"country": "United Kingdom",
"capital": "London",
"language": ["English"]
}
]
},
{
"id": 3,
"continent": "Asia",
"country": [
{
"country": "Singapore",
"capital": "Singapore",
"language": ["English","Malay","Mandarin","Tamil"]
}
]
}
]
答案 0 :(得分:1)
import 'dart:math'; //useful to check the longest list of countries
class ContinentPage2 extends StatefulWidget {
ContinentPage2() : super();
@override
_ContinentPageState createState() => _ContinentPageState();
}
class _ContinentPageState extends State<ContinentPage2> {
List<Continent> _continent = []; //initialize empty to avoid problem with the table
int maxLength; //we need to check for the longest list of countries in all the continents
@override
void initState() {
super.initState();
ContinentServices.getContinent().then((continents) {
setState(() {
_continent = continents;
maxLength = _continent.map((continent) => continent.country.length).reduce(max);
/*max uses dart:math, I made a list of the length of all the List<countries>
and then check for the list with the maximum length*/
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('')),
body: SingleChildScrollView(
child: Table(
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
columnWidths: {0: FlexColumnWidth(0.5)}, //accept a map and gives to the index the width I want, in this case the first widget a flex of 0.5, and the others will have the default 1, so it's the same as using expanded with flex: 1 and then flex: 2
children: [
for (Continent continent in _continent)
TableRow(children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Text(continent.continent),
),
for (Country country in continent.country)
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(country.name),
),
),
Flexible(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
country.capital,
style: TextStyle(
color: Colors.blue,
),
textAlign: TextAlign.center,
)),
),
//OPTION 1 create a String with all the languages as a single text
if(country.languages.isNotempty)
Flexible(
child: MyLanguages(
lang: country.languages.reduce((prev, curr) => '$prev, $curr')
)
),
// Option 2 using a for to create multiple text widgets inside the column widget with all the languages per country
if(country.languages.isNotempty)
for(String language in country.language)
Flexible(
child: Text(language)
)
]),
),
if (continent.country.length < maxLength)
for (int i = 0; i < maxLength - continent.country.length; i++)
const SizedBox()
])
],
)));
}
}
// Used in Option 1
class MyLanguages extends StatelessWidget{
final String languages;
MyLanguages({String lang, Key key}) : languages = lang.replaceFirst(',', ' and', lang.lastIndexOf(',').clamp(0, double.infinity)), super(key: key);
@override
Widget build(BuildContext context){
return Text(languages);
}
}
对于所有嵌套的行和列,我认为最好的方法是使用Table小部件,它允许用y列创建x行的表,但是只有一个问题,所有行都必须具有相同的列数(矩形或方形表格)。因此,要解决此问题,我做了一个int maxLength,然后:
maxLength = _continent.map((continent) => continent.country.length).reduce(max);
制作一个包含所有国家/地区长度且具有减少最大值的列表,我检索了具有最大长度的列表值,这对下一部分很有用
if (continent.country.length < maxLength)
for (int i = 0; i < maxLength - continent.country.length; i++)
const SizedBox()
在这里,我检查是否制作了整行,或者该行是否具有少于任何行中最大数量的小部件,然后仅添加虚拟const SizedBox()来欺骗具有相同数量小部件的表在每一行中(如果您对此部分进行注释,则将需要输入相同的列数,这将给您带来错误)。
columnWidths: {0: FlexColumnWidth(0.5)},
此行与Expanded一起用作flex,它接受map Map,其中key int是每一行中列的索引,在这种情况下,我为0,而flex为0.5,其他保留默认值1.0。如果您想尝试一下,还有其他TableColumnWidth类
最后,我将“国家/地区”包裹在垂直5的填充中,使其看起来像您的splitterbuilder SizedBox(height:10),在“列”内部,我使用了带有fit.scaleDown的Flexible和FittedBox包裹了文本,从而减小了如果文本充满所有宽度,并添加textAlign.center以使文本居中。如果您有一个很大的大文本,它将减小它的大小。如果您不希望这样做,可以只保留“文本”小部件并添加maxLines和softWrap
Text(
country.capital,
style: TextStyle(color: Colors.blue),
textAlign: TextAlign.center,
maxLines: 2, softWrap: true,
)
或者,如果您确实想要更多的自定义文字大小,则可以选中Auto_Size_Text Package
fittedBox的结果
不包含FittedBox和maxLines的结果:2,softwrap:true