Измените порядок построения SliverFixedExtentList во Flutter
У меня есть FutureBuilder на домашней странице моего приложения, которое возвращает SliverFixedExtentList после завершения будущего. Это выглядит примерно так:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:project_spruce/DataBase/DataBaseConnection.dart';
import 'package:project_spruce/states/UserState.dart';
import 'package:project_spruce/widgets/FabBottomAppBar.dart';
import 'package:project_spruce/widgets/FoodItemCard.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final List<DocumentSnapshot> _documents = List<DocumentSnapshot>();
String uid = Provider.of<UserState>(context).firebaseUser.uid;
return FutureBuilder(
future: Provider.of<DataBaseConnection>(context).getQuerySnapshot('eatenFoods/'+ uid +'/food'),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
Widget child;
if (snapshot.hasData){
_documents.clear();
snapshot.data.documents.forEach((doc)=> _documents.add(doc));
child = SliverFixedExtentList(
itemExtent: 150,
delegate: new SliverChildBuilderDelegate(
(context, index) => FoodItemCard(_documents[index]),
childCount: _documents.length,
),
);
}else {
child = SliverToBoxAdapter(child: CircularProgressIndicator());
}
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushNamed(context, '/camera_screen'),
tooltip: 'Add',
elevation: 2,
child: Icon(Icons.add),
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Colors.white,
),
bottomNavigationBar: FabBottomAppBar(
backgroundColor: Theme.of(context).primaryColor,
color: Colors.white,
selectedColor: Colors.white,
iconSize: 30,
notchedShape: CircularNotchedRectangle(),
items: [
FabBottomAppBarItem(iconData: Icons.search, text: 'Search'),
FabBottomAppBarItem(iconData: Icons.pie_chart, text: 'Statistics'),
FabBottomAppBarItem(
iconData: Icons.storage, text: 'Food Inventory'),
FabBottomAppBarItem(iconData: Icons.person, text: 'Profile'),
],
onTabSelected: (int tabIndex) {
switch (tabIndex) {
case 0:
{
// Search
Navigator.pushNamed(context, '/search');
}
break;
case 1:
{
// Statistics
Navigator.pushNamed(context, '/stats');
}
break;
case 2:
{
// Inventory
Navigator.pushNamed(context, '/inventory');
}
break;
case 3:
{
// Profile
Navigator.pushNamed(context, '/profile');
}
break;
}
},
),
body: new CustomScrollView(
slivers: <Widget>[
SliverAppBar(
//title: const Text('Home Page'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.notifications),
tooltip: 'Notifications',
onPressed: () => (){}, //(Navigator.pushNamed(context, '/notifications')),
),
],
floating: true,
pinned: true,
snap: false,
forceElevated: true,
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
title:
Text("Hi, " + Provider.of<UserState>(context).user.name),
centerTitle: false,
),
),
child,
],
)
);
}
);
}
}
Future получает список документов из базы данных, а затем передает их по порядку вспомогательному классу, который помещает данные в Card. Проблема в том, что в этой реализации самые последние документы помещаются внизу, а я хочу, чтобы они были вверху. Я могу изменить порядок получения документов из базы данныхFirestore.instance.collection(path).orderBy('date', descending: true).getDocuments();
, но поскольку список не восстанавливается полностью каждый раз, когда я возвращаюсь на страницу, новые данные вообще не отображаются, если я не перестрою приложение. Я также пробовал установитьreverse: true
в настраиваемом представлении прокрутки, но это меняет все, включая SliverAppBar.
Есть ли способ просто перевернуть способ построения SliverFixedExtentList, чтобы более высокие индексы оказались наверху?
1 ответ
Вместо того, чтобы пытаться отменить SliverFixedExtentList, вы можете отменить элементы... Все, что вам нужно сделать, это перевернуть _documents после для каждого цикла
Обратите внимание, где я добавил _documents = _documents.reversed.toList() и setState
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:project_spruce/DataBase/DataBaseConnection.dart';
import 'package:project_spruce/states/UserState.dart';
import 'package:project_spruce/widgets/FabBottomAppBar.dart';
import 'package:project_spruce/widgets/FoodItemCard.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
final List<DocumentSnapshot> _documents = List<DocumentSnapshot>();
String uid = Provider.of<UserState>(context).firebaseUser.uid;
return FutureBuilder(
future: Provider.of<DataBaseConnection>(context).getQuerySnapshot('eatenFoods/'+ uid +'/food'),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
Widget child;
if (snapshot.hasData){
setState(() {
_documents.clear();
snapshot.data.documents.forEach((doc)=> _documents.add(doc));
child = SliverFixedExtentList(
itemExtent: 150,
delegate: new SliverChildBuilderDelegate(
(context, index) => FoodItemCard(_documents[index]),
childCount: _documents.length,
),
);
});
}else {
child = SliverToBoxAdapter(child: CircularProgressIndicator());
}
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushNamed(context, '/camera_screen'),
tooltip: 'Add',
elevation: 2,
child: Icon(Icons.add),
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Colors.white,
),
bottomNavigationBar: FabBottomAppBar(
backgroundColor: Theme.of(context).primaryColor,
color: Colors.white,
selectedColor: Colors.white,
iconSize: 30,
notchedShape: CircularNotchedRectangle(),
items: [
FabBottomAppBarItem(iconData: Icons.search, text: 'Search'),
FabBottomAppBarItem(iconData: Icons.pie_chart, text: 'Statistics'),
FabBottomAppBarItem(
iconData: Icons.storage, text: 'Food Inventory'),
FabBottomAppBarItem(iconData: Icons.person, text: 'Profile'),
],
onTabSelected: (int tabIndex) {
switch (tabIndex) {
case 0:
{
// Search
Navigator.pushNamed(context, '/search');
}
break;
case 1:
{
// Statistics
Navigator.pushNamed(context, '/stats');
}
break;
case 2:
{
// Inventory
Navigator.pushNamed(context, '/inventory');
}
break;
case 3:
{
// Profile
Navigator.pushNamed(context, '/profile');
}
break;
}
},
),
body: new CustomScrollView(
slivers: <Widget>[
SliverAppBar(
//title: const Text('Home Page'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.notifications),
tooltip: 'Notifications',
onPressed: () => (){}, //(Navigator.pushNamed(context, '/notifications')),
),
],
floating: true,
pinned: true,
snap: false,
forceElevated: true,
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
title:
Text("Hi, " + Provider.of<UserState>(context).user.name),
centerTitle: false,
),
),
child,
],
)
);
}
);
}
}
Надеюсь, это сработает