Flutter:如何根据Expanded和itemCount自动调整ListView中的高度,宽度,字体大小 [英] Flutter: How to AUTO RESIZE height, width, fontSize in ListView based on Expanded and itemCount

查看:1940
本文介绍了Flutter:如何根据Expanded和itemCount自动调整ListView中的高度,宽度,字体大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的页面:


  1. 第一列表视图: Axis.vertical 默认情况下

  2. 第一个列表视图中的第二个列表视图: Axis.horizo​​ntal itemCount = 3 。为避免该错误,我为容器设置了 height:50 宽度:100 code>在此

但是,我想找到一种使其在所有屏幕上都能正常显示的方法,特别是在第二个ListView:




  • 扩展(1:1:1:1)和

  • 宽度 of 容器将基于扩展的弹性自动调整大小。

  • fontSize 文本)和 Height 容器将根据 maxLine


$自动调整大小b $ b



请帮助我,这是JSON文件

  [
{
id:1,
continent:否美国,
国家:[
{
name:美国,
首都:华盛顿特区,
语言:[英语]
},
{
国家:加拿大,
首都:渥太华,
语言 :[英语,法语]
},
{
country: Mexico,
capital: Mexico City,
语言:[西班牙语]
}
]
},
{
id:2,
大陆:欧洲,
国家:[
{
国家:德国,
首都:柏林,
语言:[德语]
},
{
country: United Kingdom,
capital: London,
language:[英语]
}
]
},
{
id:3,
continent:亚洲,
国家/地区:[
{
国家/地区:新加坡,
capital:新加坡,
language:[英语,马来人,普通话,泰米尔语]
}
]
}
]

这是主文件

  import'package:flutter / material.dart'; 
导入 model / continent_model.dart;
导入 services / continent_services.dart;

类ContinentPage2扩展了StatefulWidget {
ContinentPage2():super();

@override
_ContinentPageState createState()=> _ContinentPageState();
}

类_ContinentPageState扩展了State< ContinentPage2> {
List< Continent> _大陆;
@override
void initState(){
super.initState();
ContinentServices.getContinent()。then((continents){
setState((){
_continent =大陆;
});
});
}

@override
Widget build(BuildContext context){
return Scaffold(
appBar:AppBar(title:Text('')),
正文:ListView.separated(
eparatorBuilder:(BuildContext context,int index){
return SizedBox(height:10);
},
rinkWrap:true,
itemCount:空== _continent?0:_continent.length,
itemBuilder :(上下文,索引){
return Column(mainAxisAlignment:MainAxisAlignment.center,crossAxisAlignment:CrossAxisAlignment.center,子代: < Widget> [
Row(mainAxisAlignment:MainAxisAlignment.center,crossAxisAlignment:CrossAxisAlignment.center,mainAxisSize:MainAxisSize.min,子级:< Widget> [
Expanded(flex:1,child:Text( _continent [index] .continent)),
扩展了(
flex:2,
子代:Conta iner(
高度:50,
子级:ListView.separated(
SeparateBuilder:(BuildContext context,int index){
return SizedBox(width:10);
},
收缩包装:true,
scrollDirection:Axis.horizo​​ntal,
itemCount:null == _continent吗? 0:_continent [index] .country.length,
itemBuilder :(上下文,countryIndex){
print(_continent [index] .country [countryIndex] .name);
return Row(mainAxisAlignment:MainAxisAlignment.center,crossAxisAlignment:CrossAxisAlignment.center,children:< Widget> [
Container(
width:100,
child:Column(children: < Widget> [
Text(
_continent [index] .country [countryIndex] .name,
),
Text(_continent [index] .country [countryIndex] .capital ,
样式:TextStyle(
颜色:Colors.blue,
)),
]))
]);
})))
])
]);
}));
}
}


解决方案

  import'dart:math'; //用于检查最长的国家/地区列表

类ContinentPage2扩展了StatefulWidget {
ContinentPage2():super();

@override
_ContinentPageState createState()=> _ContinentPageState();
}

类_ContinentPageState扩展了State< ContinentPage2> {
List< Continent> _continent = []; //初始化为空以避免表
int maxLength出现问题; //我们需要检查所有大洲中最长的国家/地区列表

@override
void initState(){
super.initState();

ContinentServices.getContinent()。then((continents){
setState((){
_continent =大陆;
maxLength = _continent.map((continent) => continent.country.length).reduce(max);
/ * max使用dart:math,我列出了所有List< countries>
的长度,然后检查了具有最大长度的列表* /
});
});
}

@override
Widget build(BuildContext context){
return Scaffold(
appBar:AppBar(title:Text('')),
正文:SingleChildScrollView(
子项:Table(
defaultVerticalAlignment:TableCellVerticalAlignment.middle,
columnWidths:{0:FlexColumnWidth(0.5)},//接受地图并赋予索引我想要的宽度,在这种情况下,第一个控件的flex为0.5,其他控件的默认值为1,所以它与在flex:1和flex:2下使用expand相同:
孩子:[
用于(_大陆的大陆)
TableRow(子级:[
TableCell(
verticalAlignment:TableCellVerticalAlignment.middle,
子级:Text(continent.continent),
),
表示(大陆国家的国家/地区)
填充(
paddin g:const EdgeInsets.symmetric(vertical:5),
子级:Column(
mainAxisSize:MainAxisSize.min,
子级:< Widget> [
Flexible(
子级:FittedBox(
fit:BoxFit.scaleDown,
子级:Text(country.name),
),
),
Flexible(
孩子:FittedBox(
适合:BoxFit.scaleDown,
孩子:文本(
country.capital,
样式:TextStyle(
颜色:Colors.blue,
),
textAlign:TextAlign.center,
)),
),
//选项1创建一个字符串,将所有语言作为单个文本
if(country.languages.isNotempty)
Flexible(
child:MyLanguages(
lang:country.languages.reduce((prev,curr)=> '$ prev,$ curr')

),
//选项2使用for在列小部件内创建多个文本小部件,每个国家/地区的所有语言为
如果(country.languages.isNotempty)
for(country.language中的字符串语言)
Flexible(
child:Text(language)

]),
),如果(continent.country.length< maxLength)
for(int i = 0; i< maxLength-continent.country.length; i ++)
const SizedBox( )
])
],
)));
}
}


//在选项1中使用
类MyLanguages扩展了StatelessWidget {
最终字符串语言;

MyLanguages({String lang,Key key}):语言= lang.replaceFirst(',','和',lang.lastIndexOf(',')。clamp(0,double.infinity) ),super(key:key);

@override
小部件build(BuildContext context){
return Text(languages);
}


}

嵌套行和列我认为最好的主意是使用Table小部件,它允许用y列制作x行的表,但是只有一个问题,所有行都需要具有相同数量的列(矩形或矩形)。方桌)。因此,要解决此问题,我做了一个int maxLength,然后:

  maxLength = _continent.map((continent)=> .country.length).reduce(max); 

制作一个列表,列出所有国家/地区的长度,并使用reduce max检索具有最大长度的列表,对下一部分有用

  if(continent.country.length< maxLength)
为(int i = 0; i< maxLength-continent.country.length; i ++)
const SizedBox()

在这里,我检查是否创建了整行,或者该行是否具有少于任何行中最大数量的小部件,然后仅添加虚拟const SizedBox()来欺骗具有此属性的表。每行中的小部件数量相同(如果您对此部分进行注释,则将需要一个相同的列数,这将给您带来错误)。

  columnWidths:{0:FlexColumnWidth(0.5)},

此行用作flex使用Expanded,它接受map Map,其中键int是每一行中列的索引,在这种情况下为0,我给它一个flex 0.5,其他保持默认值为1.0。如果您想尝试一下,还有其他



不包含FittedBox和maxLines的结果:2,softwrap:true




I have a page like this:

  1. 1st Listview: Axis.vertical as default
  2. 2nd Listview inside 1st Listview: Axis.horizontal, itemCount = 3. To avoid the error, I set the height:50 width:100 for Container in this

However, I want to find some way for it to display well on all screens, specifically in the 2nd ListView:

  • Expanded (1: 1: 1) and it fits the right of the screen, can't scroll.
  • Width of Container will auto-resize based on Expanded flex.
  • fontSize of Text and Height of Container will auto-resize based on maxLine

So pls help me, this is JSON file

[
  {
    "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"]
      }
    ]
  }
]

And this is the main file

import 'package:flutter/material.dart';
import 'model/continent_model.dart';
import 'services/continent_services.dart';

class ContinentPage2 extends StatefulWidget {
  ContinentPage2() : super();

  @override
  _ContinentPageState createState() => _ContinentPageState();
}

class _ContinentPageState extends State<ContinentPage2> {
  List<Continent> _continent;
  @override
  void initState() {
    super.initState();
    ContinentServices.getContinent().then((continents) {
      setState(() {
        _continent = continents;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('')),
        body: ListView.separated(
            separatorBuilder: (BuildContext context, int index) {
              return SizedBox(height: 10);
            },
            shrinkWrap: true,
            itemCount: null == _continent ? 0 : _continent.length,
            itemBuilder: (context, index) {
              return Column(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
                Row(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[
                  Expanded(flex: 1, child: Text(_continent[index].continent)),
                  Expanded(
                      flex: 2,
                      child: Container(
                          height: 50,
                          child: ListView.separated(
                              separatorBuilder: (BuildContext context, int index) {
                                return SizedBox(width: 10);
                              },
                              shrinkWrap: true,
                              scrollDirection: Axis.horizontal,
                              itemCount: null == _continent ? 0 : _continent[index].country.length,
                              itemBuilder: (context, countryIndex) {
                                print(_continent[index].country[countryIndex].name);
                                return Row(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
                                  Container(
                                      width: 100,
                                      child: Column(children: <Widget>[
                                        Text(
                                          _continent[index].country[countryIndex].name,
                                        ),
                                        Text(_continent[index].country[countryIndex].capital,
                                            style: TextStyle(
                                              color: Colors.blue,
                                            )),
                                      ]))
                                ]);
                              })))
                ])
              ]);
            }));
  }
}

解决方案

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);
  }


}

With all the nested Rows and Columns I thought the best idea was tu use a Table widget, it allows to make a table of x rows with y columns, but there is only one problem, all the rows need to have the same amount of columns (rectangular or square table). So to work around that I made an int maxLength, then:

maxLength = _continent.map((continent) => continent.country.length).reduce(max); 

Makes a List with all the lengths of the countries and with reduce max I retrieve the value of the the list with the maximum length, useful for the next part

if (continent.country.length < maxLength)
for (int i = 0; i < maxLength - continent.country.length; i++)
   const SizedBox()

Here I check if I made a full row or if that row has less widgets that the maximum I will have in any row, and then just add dummys const SizedBox() to trick the Table that it has the same amount of widgets in every Row (if you comment this part it will give you an error because it needs to have the same amount of columns).

columnWidths: {0: FlexColumnWidth(0.5)},

This line works as flex with Expanded, it accepts a map Map where the key int is the index of the column in each row, in this case 0 and I give it a flex 0.5, and the others keep the default 1.0. There are other TableColumnWidth classes if you want to give it a try

Finally I wrapped the Countries in a Padding with vertical 5 to make it look like your separatorbuilder SizedBox(height: 10), inside the Columns I wrapped the text with a Flexible and FittedBox with fit.scaleDown so it reduce the size of the text in case it fills all the width and added the textAlign.center to center the text. In case you have a big large text it will reduce it's size to fill. If you don't want that you can keep only the Text widget and add maxLines and softWrap

Text(
  country.capital,
  style: TextStyle(color: Colors.blue),
  textAlign: TextAlign.center,
  maxLines: 2, softWrap: true,
)

Or you could check the Auto_Size_Text Package if you really want more customization with the size of the text

Result with fittedBox

Result without FittedBox and maxLines: 2, softwrap: true

这篇关于Flutter:如何根据Expanded和itemCount自动调整ListView中的高度,宽度,字体大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆