1. Введение
Flutter
Как одна из самых популярных технологий в настоящее время, она уже привлекла внимание большого количества энтузиастов технологий, и даже некоторых闲鱼
,美团
,腾讯
И другие крупные компании были введены в эксплуатацию. Хотя его экология еще не полностью созрела,Google
Благо, скорость его развития уже достаточно поразительна, можно предвидеть, что в будущемFlutter
Спрос на разработчиков также будет расти.
Будь то первые пользователи технологий или возможные вакансии в будущем, прошло уже 9102 года.Как фронтенд-разработчику, кажется, нет причин не попробовать это. Именно с таким менталитетом автор и начал изучатьFlutter
, и построилсклад, весь последующий код будет размещаться на нем, добро пожаловать звездочка, учитесь вместе. Это серия статей о Flutter, которую я написал:
- Создание красивых интерфейсов пользовательского интерфейса с помощью Flutter — основные компоненты
- Компонент контейнера прокрутки Flutter — ListView
- Компоновка сетки Flutter — статьи GridView
- Использование пользовательского значка во Flutter
В предыдущей статье мы узнали, как использоватьListView
иGridView
Эти два компонента типа прокрутки. Сегодня давайте изучим еще один компонент прокруткиCustomScrollView
и его использование сSliver
Компоненты серии. Освойте их, и вы сможете создавать интересные эффекты прокрутки~
2. Необходимые знания
Прежде чем перейти к сегодняшней теме, давайте кратко разберемся с двумя сегодняшними главными героями.CustomScrollView
иSliver
:CustomScrollView
даFlutter
Предоставленные компоненты, которые можно использовать для настройки эффекта прокрутки, можно использовать как клей для объединения несколькихSliver
склеены.
Что это обозначает? Возьмите каштан (также можно нажатьздесьСмотретьyoutube
видео выше):
если естьList
иGrid
, хотя они кажутся единым целым, но поскольку их эффекты прокрутки являются отдельными, нет гарантии согласованности эффектов прокрутки.
при использованииCustomScrollView
компоненты в виде прокручиваемых контейнеров,SliverList
иSliverGrid
соответственно заменитьList
иGrid
в видеCustomScrollView
, эффект прокрутки затем контролируетсяCustomScrollView
Единый контроль, вот и все.
вSliverList
иSliverGrid
это то, что мы упоминали ранееSliver
Два члена сериала, среди прочего,Sliver
Есть еще несколько часто используемых семейств:
-
SliverAppBar
: создает панель приложения для дизайна материалов, которую можно поместить в CustomScrollView. -
SliverPersistentHeader
: Создает полосу, размер которой меняется при прокрутке до начала области просмотра. -
SliverFillRemaining
: создает полосу, которая заполняет оставшееся пространство в окне просмотра. -
SliverToBoxAdapter
: создает полосу, содержащую виджет с одним полем. -
SliverPadding
: Создает полосу, которая применяет отступы с каждой стороны другой полоски.
Примечание: из-заCustomeScrollView
подкомпоненты могут быть толькоSliver
серии, так что если вы хотите впихнуть нормальный компонент вCustomScrollView
, то обязательно используйте этот компонент сSliverToBoxAdapter
пакет.
3. Разминка: SliverList/SliverGrid
Кажется немного скучным говорить о таком количестве концепций раньше, поэтому давайте начнем с самого простого примера и посмотрим, как его использовать.CustomScrollView
иSliverList
/SliverGrid
.
фактическиCustomScrollView
Использование простое, оно имеетslivers
собственность, представляет собойWidget
Массив, просто поместите в него все подкомпоненты, и некоторые другие свойства, связанные с прокруткой, в основном такие же, как то, что мы узнали раньше.ListView
почти.
CustomScrollView(
slivers: <Widget>[
renderSliverA(),
renderSliverB(),
renderSliverC(),
],
)
посмотри сноваSliverList
, он имеет только одинdelegate
свойства, вы можете использоватьSliverChildListDelegate
илиSliverChildBuilderDelegate
Эти два класса реализуют. Первый будет отображать все дочерние компоненты одновременно, а второй будет отображать появляющиеся в данный момент элементы в соответствии с окном просмотра, и его эффект может быть таким же, какListView
иListView.build
Два конструктора аналогичны.
SliverList(
delegate: SliverChildListDelegate(
<Widget>[
renderA(),
renderB(),
renderC(),
]
)
)
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => renderItem(context, index),
childCount: 10,
)
)
Из приведенного выше примера мы находим, чтоSliverList
как использовать иListView
почти так же, иSliverGrid
То же самое верно, поэтому я не буду вдаваться в подробности. Давайте рассмотрим пример сетки из двух столбцов:
SliverGrid.count(
crossAxisCount: 2,
children: <Widget>[
renderA(),
renderB(),
renderC(),
renderD()
]
)
Далее, давайте объединим три пункта выше с практическим примером.
Код (см. полную версиюздесь):
final List<Color> colorList = [
Colors.red,
Colors.orange,
Colors.green,
Colors.purple,
Colors.blue,
Colors.yellow,
Colors.pink,
Colors.teal,
Colors.deepPurpleAccent
];
// Text组件需要用SliverToBoxAdapter包裹,才能作为CustomScrollView的子组件
Widget renderTitle(String title) {
return SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
),
);
}
CustomScrollView(
slivers: <Widget>[
renderTitle('SliverGrid'),
SliverGrid.count(
crossAxisCount: 3,
children: colorList.map((color) => Container(color: color)).toList(),
),
renderTitle('SliverList'),
SliverFixedExtentList( // SliverList的语法糖,用于每个item固定高度的List
delegate: SliverChildBuilderDelegate(
(context, index) => Container(color: colorList[index]),
childCount: colorList.length,
),
itemExtent: 100,
),
],
)
визуализация:
Еще одна вещь, которую следует отметить в приведенном выше примере, это то, что мы поместили компонент заголовка вSliverToBoxAdapter
внутри, потому чтоCustomScrollView
принимать толькоSliver
ряд компонентов.
4. Яркий SliverAppBar
AppBar
обычно используется для создания заголовка страницыBar
компоненты, вCustomScrollView
что соответствуетSliverAppBar
компоненты. Что в нем такого волшебного? По мере прокрутки страницы заголовокBar
Будет эффект перехода коллапса. Давайте сначала посмотрим на эффект:
плавающий эффект | моментальный эффект | закрепленный эффект |
---|---|---|
Через предварительный просмотр выше, вы должны быть очень любопытныSliverAppBar
Как добиться эффекта перехода в ~ Не волнуйтесь, давайте посмотрим, как его использовать:
SliverAppBar(
floating: true,
snap: true,
pinned: true,
expandedHeight: 250,
flexibleSpace: FlexibleSpaceBar(
title: Text(this.title),
background: Image.network(
'http://img1.mukewang.com/5c18cf540001ac8206000338.jpg',
fit: BoxFit.cover,
),
),
)
SliverAppBar
Наиболее важные свойства перечислены в примере выше. в:
-
expandedHeight
: в развернутом состоянииappBar
Высота , то есть место, занимаемое картинкой на рисунке; -
flexibleSpace
: компоненты с переменным размером пространства,Flutter
предоставляет нам готовыйFlexibleSpaceBar
Компонент, сделай это для насtitle
переходный эффект.
Кроме того,floating
/snap
/pinned
Эти три свойства могут быть указаныSliverAppBar
Презентация контента после того, как он соскользнет с экрана.
-
float
: при смахивании вниз, даже если текущийCustomScrollView
не наверху,SliverAppBar
также появятся вниз вместе; -
snap
: Когда палец отпущен,SliverAppBar
будет регулироваться в соответствии с текущим положением, всегда сохраняя展开
или收起
статус; -
pinned
: отличается отfloat
эффект, когдаSliverAppBar
Когда содержимое соскальзывает с экрана, компонент свернутого состояния, закрепленный вверху, всегда будет отображаться.
нужно знать, это:snap
Эффект должен бытьfloat
заtrue
вступит в силу. Кроме того, вы можете использовать комбинацию из трех.
5. Разновидности SliverPersistentHeader
В предыдущем разделе мы виделиSliverAppBar
Его магия в том, что он основан наSliverPersistentHeader
осуществленный. пройти черезSliverPersistentHeader
, мы также можем достичьsticky
эффект потолка.
SliverPersistentHeader
Наиболее важным атрибутом являетсяSliverPersistentHeaderDelegate
, для этого нам нужно реализовать класс, который наследуется отSliverPersistentHeaderDelegate
.
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
@override
double get minExtent => null;
@override
double get maxExtent => null;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => null;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => null;
}
можно увидеть,SliverPersistentHeaderDelegate
Класс реализации должен реализовать свои 4 метода. в:
-
minExtent
: высота компонента в убранном состоянии; -
maxExtent
: высота компонента в развернутом состоянии; -
shouldRebuild
: что-то типаreact
серединаshouldComponentUpdate
; -
build
: Создайте визуализированный контент.
Далее мы реализуемTabBar
эффект потолка.
Код (см. полную версиюздесь):
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
// ...
),
SliverPersistentHeader( // 可以吸顶的TabBar
pinned: true,
delegate: StickyTabBarDelegate(
child: TabBar(
labelColor: Colors.black,
controller: this.tabController,
tabs: <Widget>[
Tab(text: 'Home'),
Tab(text: 'Profile'),
],
),
),
),
SliverFillRemaining( // 剩余补充内容TabBarView
child: TabBarView(
controller: this.tabController,
children: <Widget>[
Center(child: Text('Content of Home')),
Center(child: Text('Content of Profile')),
],
),
),
],
)
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
final TabBar child;
StickyTabBarDelegate({@required this.child});
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return this.child;
}
@override
double get maxExtent => this.child.preferredSize.height;
@override
double get minExtent => this.child.preferredSize.height;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
визуализация:
Из приведенного выше рисунка видно, что при следующемtab
После того, как содержимое соскользнет с экрана,tabBar
Вместо того, чтобы соскользнуть, он прилип к вершине. видимыйSliverPersistentHeader
действительно удовлетворить нашиsticky
Эффект.
ноSliverPersistentHeader
Магия — это гораздо больше~ В конце концов, мы можем настроить некоторые эффекты перехода головы через него.SliverAppBar
Это также достигается через него. Например, эффект перехода головы на странице сведений о фильме ниже довольно распространен в обычных приложениях.
Так как же можно добиться этого эффекта? Дело в томbuild
в методеshrinkOffset
Свойство, представляющее смещение прокрутки текущего заголовка. На его основе мы можем рассчитать текущую закрытую головку背景颜色
а также иконки и текст字体颜色
, чтобы вы могли получить эффект перехода в соответствии с текущей позицией~
Код (см. полную версиюздесь):
class SliverCustomHeaderDelegate extends SliverPersistentHeaderDelegate {
final double collapsedHeight;
final double expandedHeight;
final double paddingTop;
final String coverImgUrl;
final String title;
SliverCustomHeaderDelegate({
this.collapsedHeight,
this.expandedHeight,
this.paddingTop,
this.coverImgUrl,
this.title,
});
@override
double get minExtent => this.collapsedHeight + this.paddingTop;
@override
double get maxExtent => this.expandedHeight;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
Color makeStickyHeaderBgColor(shrinkOffset) {
final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255).clamp(0, 255).toInt();
return Color.fromARGB(alpha, 255, 255, 255);
}
Color makeStickyHeaderTextColor(shrinkOffset, isIcon) {
if(shrinkOffset <= 50) {
return isIcon ? Colors.white : Colors.transparent;
} else {
final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255).clamp(0, 255).toInt();
return Color.fromARGB(alpha, 0, 0, 0);
}
}
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
height: this.maxExtent,
width: MediaQuery.of(context).size.width,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
// 背景图
Container(child: Image.network(this.coverImgUrl, fit: BoxFit.cover)),
// 收起头部
Positioned(
left: 0,
right: 0,
top: 0,
child: Container(
color: this.makeStickyHeaderBgColor(shrinkOffset), // 背景颜色
child: SafeArea(
bottom: false,
child: Container(
height: this.collapsedHeight,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: this.makeStickyHeaderTextColor(shrinkOffset, true), // 返回图标颜色
),
onPressed: () => Navigator.pop(context),
),
Text(
this.title,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: this.makeStickyHeaderTextColor(shrinkOffset, false), // 标题颜色
),
),
IconButton(
icon: Icon(
Icons.share,
color: this.makeStickyHeaderTextColor(shrinkOffset, true), // 分享图标颜色
),
onPressed: () {},
),
],
),
),
),
),
),
],
),
);
}
}
Вышеприведенный код длинный, но в основном строитwidget
код. Поэтому мы ориентируемся наmakeStickyHeaderTextColor
иmakeStickyHeaderBgColor
Вот и все. Оба метода основаны на текущемshrinkOffset
value вычисляет значение цвета во время перехода. Кроме того, здесь следует отметить, что голова находится вiPhoneX
И над дизайном головы челки вы можете использоватьSafeArea
Компоненты решают проблему.
6. Резюме
Эта статья впервые знакомитCustomScrollView
иSliver
Понятие о компонентах ряда и их взаимосвязях, сопровождаемоеSliverList
иSliverGrid
Комбинированный пример иллюстрирует его использование. Затем чаще используетсяSliverAppBar
компоненты, объясняя ихfloat
/snap
/pinned
соответствующие эффекты. Наконец-то объяснилSliverPersistentHeader
Как использовать компонент и использовать практические примеры, чтобы проиллюстрировать использование его пользовательского эффекта перехода. Я надеюсь, что благодаря введению этой статьи вы сможете использоватьCustomScrollView
иSliver
Компоненты серии создают более интересные эффекты прокрутки~
Весь код в этой статье размещен по адресуздесь, вы также можете подписаться на меняBlog, добро пожаловать, чтобы обменяться и учиться вместе~