У меня есть TabBarView () с множеством разных представлений. Я хочу, чтобы они были столбцом с TextField вверху и ListView.Builder () внизу, но оба виджета должны находиться в одной и той же прокручиваемой области (scrollview). То, как я это реализовал, вызывало некоторые ошибки:
@override
Widget build(BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: new TextField(
decoration: new InputDecoration(
hintText: "Type in here!"
),
)
),
new ListView.builder(
itemCount: _posts.length, itemBuilder: _postBuilder)
],
);
}
Ошибка:
I/flutter (23520): The following assertion was thrown during performResize():
I/flutter (23520): Vertical viewport was given unbounded height.
I/flutter (23520): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter (23520): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter (23520): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter (23520): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter (23520): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter (23520): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter (23520): the height of the viewport to the sum of the heights of its children.
Я читал о размещении ListView.builder () в расширенной области, но это сделало текстовое поле «липким», чего я не хочу. :-)
Я также наткнулся на CustomScrollView, но не совсем понимал, как его реализовать.





Column не прокручивается, поэтому TextField вверху не прокручивается, а ListView внизу -.
На мой взгляд, лучший способ решить эту проблему - сделать ваш TextField первым элементом в вашем ListView.
Таким образом, столбец вам не понадобится, ваш родительский виджет - это ListView, а его дочерние элементы - это TextField, за которыми следуют остальные элементы, которые вы создаете с помощью _postBuilder.
Размещение ListView внутри виджета Expanded должно решить вашу проблему:
@override
Widget build(BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: new TextField(
decoration: new InputDecoration(
hintText: "Type in here!"
),
)
),
new Expanded(child: ListView.builder(
itemCount: _posts.length, itemBuilder: _postBuilder))
],
);
}
Насколько я понял, Expanded и ListView работают вместе, потому что расширенный использует остальную часть экрана. Итак, если вам нужна кнопка под расширенным, у вас сначала есть текстовое поле с заполнением, затем расширенное (с возможностью прокрутки), а затем кнопка в нижней части экрана.
Если у вас возникли проблемы с этим решением, проверьте, находится ли столбец внутри Positioned. Если это так, вам нужно указать верх и низ. Так дротик может рассчитать размер. Если указать только верхнюю часть, для расчета не хватит данных.
Лучше всего сделать столбец прокручиваемым, сделав столбец дочерним элементом SingleChildScrollView, а затем назначив один и тот же ScrollController как для SingleChildScrollView, так и для ListView.builder. Это сделает текстовое поле и расположенный ниже ListView прокручиваемым.
Причина ошибки:
Column расширяется до максимального размера в направлении главной оси (вертикальной оси), как и ListView.
Решение
Вам необходимо ограничить высоту ListView, чтобы он расширялся, чтобы соответствовать Column. Есть несколько способов решения этой проблемы, я перечисляю некоторые из них:
Если вы хотите, чтобы ListView занимал все оставшееся пространство внутри Column, используйте Flexible.
Column(
children: <Widget>[
Flexible(
child: ListView(...),
)
],
)
Если вы хотите ограничить свой ListView определенным height, вы можете использовать SizedBox.
Column(
children: <Widget>[
SizedBox(
height: 200, // constrain height
child: ListView(),
)
],
)
Если ваш ListView маленький, вы можете попробовать на нем свойство shrinkWrap.
Column(
children: <Widget>[
ListView(
shrinkWrap: true, // use it
)
],
)
Номер 3 спас мою проблему. Спасибо, отличный ответ!
Я получаю Incorrect use of ParentDataWidget. с помощью метода 1
@PiyushChauhan Вы могли пропустить включение Column. Если это не так, задайте отдельный вопрос, и я буду рад вам помочь.
У меня не было гибкого виджета вокруг моего Listview - только расширенный виджет вокруг части столбца, потомком которого он был. Это мне очень помогло, спасибо!
Вот решение:
SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: <Widget>[
Text('Hey'),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount:18,
itemBuilder: (context,index){
return Text('Some text');
})
],
),
),
Боже мой, ты лучший. Я искал это решение 1 месяц
у меня это не сработало, мне нужно было добавить атрибут для columnMainAxisSize.min, чтобы он работал.
Хотел бы я проголосовать за это 100 раз ... Наконец-то это заработало.
Приемлемый ответ :)
@PedroMolina Вы добавили shrinkWrap: true в свой ListView, потому что он работает без него. Однако благодаря @SunpreetSingh
«Физика: NeverScrollableScrollPhysics ()» спасла меня. Спасибо!
Спасибо тебе большое, братан
Ты спас мне день. Мне всегда было интересно, почему NeverScrollableScrollPhysics () вообще существует. Теперь я знаю почему: D
@ Санприт Сингх, ты легенда!
сэкономил мне столько часов !! "физика: NeverScrollableScrollPhysics ()"
Используйте виджет Расширенный, чтобы ограничить, не переполняя эти пиксели, :)
Column(
children: <Widget>[
Expanded(
child: ListView(),
),
Expanded(
child: ListView(),
),
],
)
Просто добавьте физика: NeverScrollableScrollPhysics () в ListView.builder (), чтобы можно было прокручивать
Пожалуйста, включите больше контекста в ответы
Добавьте physics: NeverScrollableScrollPhysics() в метод Listview.builder(), и вложенный Listview будет прокручиваться
Решение
SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
Здесь используются два свойства
shrinkWrap: true
занимает только необходимое пространство (он все равно будет прокручиваться, когда будет больше элементов).
physics: NeverScrollableScrollPhysics()
Физика прокрутки, которая не позволяет пользователю прокручивать. Имеется ввиду только работа Column + SingleChildScrollView Scrolling.
Это решение неэффективно, потому что в представлении списка все элементы будут немедленно построены, что устранит выигрыш в производительности.
@kemist: Какое тогда будет идеальное решение?
@ jitsm555 Вы хотите использовать CustomScrollView с SliverList и SliverChildBuilderDelegate.
@ jitsm555 проверьте мое решение: stackoverflow.com/a/65340391/9695723
спасибо, чувак, действительно круто
В моем случае с будущим я сделал это так:
SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Hey ho let's go!"),
Flexible(
child: FutureBuilder(
future: getData(),
builder: (BuildContext context,
AsyncSnapshot<List<Sale>> snapshot) {
if (snapshot.connectionState != ConnectionState.done ||
snapshot.hasData == null) {
return CircularProgressIndicator();
} else {
data = snapshot.data;
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return dataItemWidget(size, data[index], context);
},
itemCount: data.length,
);
}
},
),
),
],
),
),
Используйте физика: NeverScrollableScrollPhysics () и shrinkWrap: true внутри ListView.Builder () и наслаждайтесь
Вот эффективное решение:
class NestedListExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
const SliverToBoxAdapter(
child: Text('Header'),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, index) {
return ListTile(title:Text('Item $index'));
},
),
),
],
);
}
}
Вот предварительный просмотр на дартпаде.
Вы можете использовать SliverToBoxAdapter для других дочерних элементов, поскольку только Slivers могут быть прямыми дочерними элементами CustomScrollView.
Если все элементы списка имеют одинаковую высоту, вы можете использовать SliverFixedExtentList, что более эффективно, потому что высота каждого дочернего элемента не рассчитывается на лету, но вам нужно будет знать точную высоту в пикселях. Вы также можете использовать SliverPrototypeExtentList, где вы указываете первый элемент в списке (прототип), а все остальные дочерние элементы будут использовать высоту прототипа, поэтому вам не нужно знать точную высоту в пикселях.
это абсолютно лучшее решение для любого списка приличного размера
//If you want Listview.builder inside ListView and want to scroll the parent ListView// //whenever the Items in ListView.builder ends or start you can do it like this
body: ListView(
physics: ScrollPhysics(),
children: [
SizedBox(height: 20),
Container( height: 110.0 *5, // *5 to give size to the container //according to items in the ListView.builder. Otherwise will give hasSize Error
child:ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: 5,
itemBuilder: (BuildContext context, int indexChild) {
return InkWell(child:Container(height:100));}))
),]),
enter code here
shrinkWrap: false,
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (контекст, индекс) {
return Row (
crossAxisAlignment: CrossAxisAlignment.start,
дети: [
Текст («привет»),
],
);
}),)
],);просто добавь
Column(
mainAxisSize: MainAxisSize.max, //Add this line onyour column
children:[
SomeWidget(),
Expanded(child:ListView.builder())
]
)
Оберните ListView расширенным виджетом