во флаттереListView
является одним из наиболее часто используемых прокручиваемых компонентов,
ЭтоВсе подкомпоненты могут быть расположены линейно в одном направлении, а также поддерживает модели отложенной сборки на основе Sliver.
Отложенная сборка на основе Sliver
Что представляет собой модель отложенной сборки, основанная на Sliver?
Часто прокручиваемые компоненты могут иметь очень много подкомпонентов и занимать очень большую общую высоту; создавать их все сразу было бы очень дорого! С этой целью Flutter предлагает концепцию Sliver (что означает «срезы» на китайском языке).Если прокручиваемый компонент поддерживает модель Sliver, то прокрутка может разделить подкомпоненты на несколько «щепок» (Sliver), только когда Sliver появляется в строиться только тогда, когда он находится в окне просмотра, эта модель также известна как «модель отложенного строительства на основе Sliver».
Пример исходного кода
Конструктор выглядит следующим образом:
ListView({
...
//可滚动组件的公共参数
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
EdgeInsetsGeometry padding,
//ListView各个构造函数的共同参数
this.itemExtent,
bool shrinkWrap = false,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
//子组件列表
List<Widget> children = const <Widget>[],
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
})
объяснение атрибута
scrollDirection
Определить направление качения дочерней сборки (расположенное направление), по умолчанию — вертикальное направление.
scrollDirection:Axis.horizontal,
горизонтальное направление
scrollDirection:Axis.vertical,
вертикальное направление
reverse
Определить направление прокрутки соответствует направлению для чтения
primary
значениеtrue
илиfalse
, я пробовал, вроде бесполезно, не знаю то ли я не так понял, то ли что, напишите сначала
controller
Это свойство получает одинScrollController
объект.ScrollController
.
СвязанныйScrollController
Для использования и подробностей, пожалуйста, обратитесь кЭлементы управления прокруткой Flutter -> Мониторинг и контроль прокрутки (ScrollController)
По умолчанию в дереве виджетов будет дефолтPrimaryScrollController
, если прокручиваемый компонент в поддереве явно не указанcontroller
,а такжеprimary
Стоимость свойстваtrue
когда (по умолчаниюtrue
), прокручиваемый компонент будет использовать это значение по умолчанию.PrimaryScrollController
. Преимущества такого механизмаРодительский компонент может управлять поведением прокрутки прокручиваемых компонентов в поддереве.,
physics
Это свойство принимает одинScrollPhysics
Тип объектов, он определяет, как компоненты прокрутки реагируют на действия пользователя, например, когда пользователь проводит пальцем вверх, продолжает выполнять анимацию или перемещается к границе, как отображать.
shrinkWrap
Атрибут указывает, чтобы установить общую длину подсагмерыListView
false
.
по умолчанию,ListView
会在滚动方向尽可能多的占用空间。 когдаListView
shrinkWrap
должно бытьtrue
itemExtent
Если этот параметр неnull
, это заставитchildren
"длина" этоitemExtent
значение;
itemExtent
itemExtent
addAutomaticKeepAlives
Это свойство указывает, следует ли обернуть элемент списка (дочерний компонент) вAutomaticKeepAlive
в компоненте;
В лениво загружаемом списке, если вы оберните элементы списка вAutomaticKeepAlive
, элемент списка не будет переработан, когда он выскользнет из окна просмотра, он будет использоватьKeepAliveNotification
сохранить его состояние. Если элемент списка поддерживает свой собственныйKeepAlive
статус, то этот параметр должен быть установлен вfalse
.
addRepaintBoundaries
Это свойство указывает, следует ли обернуть элемент списка (дочерний компонент) вRepaintBoundary
в компоненте.
Когда прокручиваемый компонент прокручивается, оберните элемент списка вRepaintBoundary
можно избежатьБесплатная перерисовка элемента списка, но не добавляет, когда накладные расходы из элемента списка RedRawing очень маленький (как блок цвета, или короткий текст)RepaintBoundary
Наоборот, это будет более эффективно. а такжеaddAutomaticKeepAlive
Например, если элемент списка поддерживает свой собственныйKeepAlive
статус, то этот параметр должен быть установлен вfalse
.
addSemanticIndexes
Это свойство указывает, следует ли обернуть дочерний элемент управления вIndexedSemantics
, используемый для обеспечения семантики доступности
cacheExtent
Видимая область будет иметь определенную высоту, чтобы перейти к подсчете кэш-памяти, и его можно быстро представить при скольжении.
Проще говоря, когда вы собираетесь провести пальцем, чтобы загрузить данные, они были загружены на один шаг раньше, и они будут отображаться, когда вы проводите к ним, вместо того, чтобы некоторое время ждать, пока пользователь проведет к ним.
semanticChildCount
Такие как:ListView
буду использоватьchildren
ListView.separated
буду использоватьchildren
Половина длины
children
здесьchildren
здесьchildren
параметры, он получит список,Но этот метод подходит для случая, когда имеется лишь небольшое количество подкомпонентов.. Потому что этот метод требует всехchildren
создаются раньше времени (что много работы), а не ждет, пока дочерний компонент на самом деле не отобразится, то есть.построен через конструктор по умолчаниюListView
Модель ленивой загрузки на основе Sliver не применяется..
Опять же, прокручиваемые компоненты проходятList
как егоchildren
При использовании свойств это применимо только к случаям с несколькими подкомпонентами, что является общим правилом.
ListView.builder
надchildren
Подходит только для использования с меньшим объемом данных
а такжеListView.builder
Он подходит для использования, когда имеется много (или неограниченное количество) элементов списка, потому что он будет создан только тогда, когда подкомпонент действительно отображается, то естьсозданный этим конструкторомListView
Он поддерживается моделями ленивой загрузки на основе SLIVER.
Пример исходного кода
Конструктор выглядит следующим образом:
ListView.builder({
// ListView公共参数已省略
...
@required IndexedWidgetBuilder itemBuilder,
int itemCount,
...
})
объяснение атрибута
itemBuilder
Это строитель для элементов списка, типаIndexedWidgetBuilder
, возвращаемое значение — это виджет (то есть компонент). Когда список прокручивается до определенногоindex
Когда местоположение достигнуто, вызывается конструктор для создания элемента списка, который представляет собой так называемую модель ленивой загрузки на основе Sliver.
itemCount
Это свойство представляет количество элементов списка, если оноnull
, это означает бесконечный список
ListView.builder(
itemCount: 100,
itemExtent: 50.0, //强制高度为50.0,如果这个值越来越小的话,那么显示的值是会重叠的
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
})
текущий результат:
ListView.separated
ListView.separated
Компонент разделения может быть добавлен между сгенерированными элементами списка.
это лучше, чемListView.builder
один дополнительныйseparatorBuilder
параметр, который является генератором разделенных компонентов.
Пример кода:
Добавьте синее подчеркивание к нечетным строкам и красное подчеркивание к четным строкам.
import 'package:flutter/material.dart';
class CategoryPage extends StatefulWidget {
@override
_CategoryPageState createState() => _CategoryPageState();
}
class _CategoryPageState extends State<CategoryPage> {
@override
Widget build(BuildContext context) {
//下划线widget预定义以供复用。
Widget Lineblue = Divider(color: Colors.blue);
Widget Linered = Divider(color: Colors.red);
return Scaffold(
appBar: AppBar(
title: Text(
"ListView.separated",
// style: TextStyle(color: Color(0xFF1E88E5)),
),
),
body: ListView.separated(
itemCount: 100,
//列表项构造器
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
},
//分割器构造器
separatorBuilder: (BuildContext context, int index) {
return index % 2 == 0 ? Lineblue : Linered;
},
));
}
}
текущий результат:
ListView
экспонат.
Здесь нам нужно установить пакетenglish_words: ^3.1.5
(существуетpubspec.yaml
в файлеdependencies
Пример кода:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
class CategoryPage extends StatefulWidget {
@override
_CategoryPageState createState() => _CategoryPageState();
}
class _CategoryPageState extends State<CategoryPage> {
static const loadingTag = "##loading##"; //表尾标记
var _words = <String>[loadingTag];
@override
void initState() {
super.initState();
_retrieveData();
}
@override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: _words.length,
itemBuilder: (context, index) {
//如果到了表尾
if (_words[index] == loadingTag) {
//不足100条,继续获取数据
if (_words.length - 1 < 100) {
//获取数据
_retrieveData();
//加载时显示loading
return Container(
padding: const EdgeInsets.all(16.0),
alignment: Alignment.center,
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(strokeWidth: 2.0)),
);
} else {
//已经加载了100条数据,不再获取数据。
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16.0),
child: Text(
"没有更多了",
style: TextStyle(color: Colors.grey),
));
}
}
//显示单词列表项
return ListTile(title: Text(_words[index]));
},
separatorBuilder: (context, index) => Divider(height: .0),
);
}
void _retrieveData() {
Future.delayed(Duration(seconds: 2)).then((e) {
_words.insertAll(
_words.length - 1,
//每次生成20个单词
generateWordPairs().take(20).map((e) => e.asPascalCase).toList());
setState(() {
//重新构建列表
});
});
}
}
_retrieveData()
Функция состоит в том, чтобы имитировать асинхронную выборку данных из источника данных,
english_words
упаковкаgenerateWordPairs()
Метод может генерировать 20 слов за раз.
текущий результат:
ListTile
Здесь мы говоримListTile
.
ListTile
Обычно используется для заполнения в трепетанииListView
.
Пример исходного кода:
Конструктор выглядит следующим образом:
const ListTile({
Key key,
this.leading,
this.title,
this.subtitle,
this.trailing,
this.isThreeLine = false,
this.dense,
this.contentPadding,
this.enabled = true,
this.onTap,
this.onLongPress,
this.selected = false,
})
объяснение атрибута
title
title
Параметр может принимать любой виджет, но обычно это текстовый виджет.
Пример кода:
ListTile(
title: Text('我喜欢你!'),
)
subtitle
Он отображается субтитром меньший текст в заголовке (заголовок) ниже
Пример кода:
ListTile(
title: Text('我喜欢你!'),
subtitle: Text('你喜欢我吗?'),
)
dense
Уменьшите текст и соберите все вместе
Пример кода:
ListTile(
title: Text('我喜欢你!'),
subtitle: Text('你喜欢我吗?'),
dense:true,
)
leading
Добавьте изображение или значок в начало списка.
Пример кода:
ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
),
title: Text('我喜欢你'),
subtitle: Text('你喜欢我吗?'),
dense:true,
)
trailing
Поместите изображение в конец списка.
Пример кода:
ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
),
title: Text('我喜欢你'),
subtitle: Text('你喜欢我吗?'),
dense:true,
trailing: Icon(Icons.keyboard_arrow_right),
)
contentPadding
Установите содержимое полей, по умолчанию 16
Я поставил 30 здесь
Пример кода:
ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
),
title: Text('我喜欢你'),
subtitle: Text('你喜欢我吗?'),
dense:true,
trailing: Icon(Icons.keyboard_arrow_right),
contentPadding: EdgeInsets.symmetric(horizontal: 30.0),
)
selected
Если список выбранitem
пункт, то цвет текста и значков будет основным цветом темы.
Пример кода:
ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
),
title: Text('我喜欢你'),
subtitle: Text('你喜欢我吗?'),
dense:true,
trailing: Icon(Icons.keyboard_arrow_right),
contentPadding: EdgeInsets.symmetric(horizontal: 30.0),
selected: true,
)
onTap, onLongPress
onTap
нажать,onLongPress
При длительном нажатии.
Пример кода:
ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
),
title: Text('我喜欢你'),
subtitle: Text('你喜欢我吗?'),
dense:true,
trailing: Icon(Icons.keyboard_arrow_right),
contentPadding: EdgeInsets.symmetric(horizontal: 30.0),
selected: true,
onTap: () {
// do something
},
onLongPress: (){
// do something else
},
)
enabled
Кenable
Установить какfalse
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
class CategoryPage extends StatefulWidget {
@override
_CategoryPageState createState() => _CategoryPageState();
}
class _CategoryPageState extends State<CategoryPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ListTile'),),
body: Column(
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('images/Test.jpg'),
),
title: Text('我喜欢你'),
subtitle: Text('你喜欢我吗?'),
dense: true,
trailing: Icon(Icons.keyboard_arrow_right),
contentPadding: EdgeInsets.symmetric(horizontal: 30.0),
// selected: true,
onTap: () {
// do something
},
onLongPress: () {
// do something else
},
),
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('images/Test.jpg'),
),
title: Text('我喜欢你'),
subtitle: Text('你喜欢我吗?'),
dense: true,
trailing: Icon(Icons.keyboard_arrow_right),
contentPadding: EdgeInsets.symmetric(horizontal: 30.0),
selected: true,
onTap: () {
// do something
},
onLongPress: () {
// do something else
},
)
],
));
}
}
текущий результат:
Добавить фиксированный заголовок списка
Много раз нам нужно добавить в список фиксированный заголовок.
Нам нужно получитьListView
Автоматически растягивать по размеру экрана, на этот раз нам нужно использовать эластичную компоновку.Flex
, если вы не знаете, пожалуйста, переместитеЭлементы управления Flutter Layout -> Flex, расширенный
мы можем использоватьExpanded
Автоматически растягиваться размер компонента, и мы также сказалиColumn
Это унаследовано отFlex
, Таким образом, мы можем напрямую использоватьColumn+Expanded
реализовать,
Пример кода:
Column(children: <Widget>[
ListTile(title: Text("数字列表")),
Expanded(
child: ListView.builder(itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
}),
),
]);
текущий результат: