Анимация изменений в SliverList
У меня сейчас есть SliverList
чьи элементы загружаются динамически. Проблема заключается в том, что после загрузки этих SliverList
обновления без анимации изменений, что делает переход между загрузкой и загрузкой очень резким.
я вижу это AnimatedList
существует, но это не осколок, поэтому я не могу поместить его прямо в CustomScrollView
,
0 ответов
Вы, наверное, знаете об этом сейчас, но можете упомянуть об этом здесь, чтобы помочь людям.
Вы можете использовать SliverAnimatedList. Достигает желаемого результата.
Конструкция SliverAnimatedList:
itemBuilder
определяет способ создания новых предметов. Строитель обычно должен возвращатьTransition
виджет или любой виджет, который будет использовать animation
параметр.
SliverAnimatedList(
key: someKey,
initialItemCount: itemCount,
itemBuilder: (context, index, animation) => SizeTransition(
sizeFactor: animation,
child: SomeWidget()
)
)
Добавление / удаление динамически
Вы делаете это, используя insertItem
а также removeItem
методы SliverAnimatedListState
. Вы можете получить доступ к состоянию либо:
- предоставление
Key
кSliverAnimatedList
и использоватьkey.currentState
- с помощью
SliverAnimatedList.of(context)
статический метод.
В случаях, когда вам нужно внести изменения извне списка, вам всегда нужно будет использовать ключ.
Вот полный пример, чтобы прояснить ситуацию. Элементы добавляются нажатием наFloatingActionButton
и удаляются касанием самого элемента. Я использовал какkey
а также of(context)
способы доступа к SliverAnimatedListState
.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SliverAnimatedListTest extends StatefulWidget {
@override
_SliverAnimatedListTestState createState() => _SliverAnimatedListTestState();
}
class _SliverAnimatedListTestState extends State<SliverAnimatedListTest> {
int itemCount = 2;
// The key to be used when accessing SliverAnimatedListState
final GlobalKey<SliverAnimatedListState> _listKey =
GlobalKey<SliverAnimatedListState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Sliver Animated List Test")),
// fab will handle inserting a new item at the last index of the list.
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_listKey.currentState.insertItem(itemCount);
itemCount++;
},
),
body: CustomScrollView(
slivers: <Widget>[
SliverAnimatedList(
key: _listKey,
initialItemCount: itemCount,
// Return a widget that is wrapped with a transition
itemBuilder: (context, index, animation) =>
SizeTransition(
sizeFactor: animation,
child: SomeWidget(
index: index,
// Handle removing an item using of(context) static method.
// Returned widget should also utilize the [animation] param
onPressed: () {
SliverAnimatedList.of(context).removeItem(
index,
(context, animation) => SizeTransition(
sizeFactor: animation,
child: SomeWidget(
index: index,
)));
itemCount--;
}),
))
],
),
);
}
}
class SomeWidget extends StatelessWidget {
final int index;
final Function() onPressed;
const SomeWidget({Key key, this.index, this.onPressed}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: FlatButton(
child: Text("item $index"),
onPressed: onPressed,
)));
}
}
Вы можете использовать неявно анимированный переупорядочиваемый список
import 'package:implicitly_animated_reorderable_list/implicitly_animated_reorderable_list.dart';
import 'package:implicitly_animated_reorderable_list/transitions.dart';
...
SliverImplicitlyAnimatedList<Comment>(
items: comments,
areItemsTheSame: (a, b) => a.id == b.id,
itemBuilder: (BuildContext context, Animation<double> animation, Comment item, int index) {
return SizeFadeTransition(
sizeFraction: 0.7,
curve: Curves.easeInOut,
animation: animation,
child: CommentSliver(
comment: item,
),
);
},
);
У меня есть обходной путь для использования простого ListView с Sliver. Он не идеален и имеет ограничения, но он работает для случая, когда у вас есть только 2 Slivers, AppBar и SliverList.
NestedScrollView(
headerSliverBuilder: (_, _a) => SliverAppBar(<Insert Code Here>),
body: MediaQuery.removePadding(
removeTop: true,
context: context,
child: AnimatedList(
<InsertCodeHere>
)))
Вы можете настроить дерево виджетов, но это основная идея. Оберните небольшую панель приложений в NestedScrollView и поместите список в тело.
Вы можете обернуть элементы списка в AnimatedWidget
Об этом читайте в документации AnimatedWidget