为什么我无法在 Future 构建器中更改 PageView.builder 中的页面?
Why am I unable to change page in PageView.builder inside Future builder?
我在未来的构建器中使用 pageview.builder 时遇到问题。它正在分页的项目是卡片,我以前确实有这个工作,但是在实现逻辑来获取笔记和我去使用未来构建器的东西并将这个 NoteSet 移到它自己的 class 中。我想我在某个地方做了重大改变,但我不确定。奇怪的是,我可以构建并查看卡片。封闭的手势检测器也能正常工作,但我无法翻阅 pageview.builder.
非常感谢任何帮助!
class NoteSet extends StatefulWidget {
VoidCallback callback;
final Category category;
NoteSet(this.category, this.callback);
@override
_NoteSetState createState() => _NoteSetState();
}
class _NoteSetState extends State<NoteSet> {
List<NoteEntry> sortedNotes = [];
double currentPage;
bool largeCards = false;
SortMethod currentSortMethod = SortMethod.CreatedDescending;
Future<List<NoteEntry>> getNotes() async {
return await readCategoryNotes(widget.category);
}
void sortNotes(){...}
refresh() {...}
deleteCategory() async {
deleteCategoryDialog(context, widget.category, refresh);
}
void toggleModifiedSort(){
currentSortMethod == SortMethod.ModifiedDescending ? currentSortMethod = SortMethod.ModifiedAscending : currentSortMethod = SortMethod.ModifiedDescending;
refresh();
}
void toggleCreatedSort(){
currentSortMethod == SortMethod.CreatedDescending ? currentSortMethod = SortMethod.CreatedAscending : currentSortMethod = SortMethod.CreatedDescending;
refresh();
}
void toggleCardSize(){
largeCards = !largeCards;
refresh();
}
void moveThisCategoryUp() async {
await moveCategoryUp(widget.category);
refresh();
}
void moveThisCategoryDown() async {
await moveCategoryDown(widget.category);
refresh();
}
@override
Widget build(BuildContext context) {
PageController controller = PageController();
currentPage = (sortedNotes.length - 1).roundToDouble();
return Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(widget.category.toString().split(".").last,
style: TextStyle(
color: Colors.white,
fontSize: 46.0,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
)
),
PopupMenuButton<VoidCallback>(...),
],
),
),
FutureBuilder(
future: getNotes(),
builder: (context, snapshot){
if(snapshot.hasData){
sortedNotes = snapshot.data;
sortNotes();
controller.addListener(() {
setState(() {
currentPage = controller.page;
});
});
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
Text("${sortedNotes.length} Entries",
style: TextStyle(color: Colors.tealAccent[200]))
],
),
),
Stack(
children: <Widget>[
CardScrollWidget(currentPage, sortedNotes, largeCards ? 0.8 : 1.2),
Positioned.fill(
child: GestureDetector(
onTap: () {
editNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
onLongPress: () {
deleteNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
child: ScrollConfiguration(
behavior: PageScrollBehavior(),
child: PageView.builder(
itemCount: sortedNotes.length,
controller: controller,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
),
),
)
],
),
],
);
}
else{
return Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SpinKitPulse(
color: Colors.tealAccent,
size: 60.0,
),
),
);
}
},
),
SizedBox(height: 15,),
],
);
}
}
好的,所以我发现了我的问题,每次构建 NoteSet 时,它都会将 currentPage 变量设置为初始页面。我还删除了 future 构建器,而是在 init 上调用 future,然后在找到数据时刷新。这是我更正的代码:
class NoteSet extends StatefulWidget {
VoidCallback callback;
final Category category;
NoteSet(this.category, this.callback);
@override
_NoteSetState createState() => _NoteSetState();
}
class _NoteSetState extends State<NoteSet> {
List<NoteEntry> sortedNotes = [];
double currentPage = 0;
bool largeCards = false;
bool dataReady = false;
SortMethod currentSortMethod = SortMethod.CreatedDescending;
Future getNotes() async {
dataReady = false;
refresh();
sortedNotes = await readCategoryNotes(widget.category);
currentPage = (sortedNotes.length - 1).roundToDouble();
dataReady = true;
refresh();
}
void sortNotes(){...}
refresh() {
widget.callback();
this.setState((){});
sortNotes();
}
...
@override
void initState() {
getNotes();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(widget.category.toString().split(".").last,
style: TextStyle(
color: Colors.white,
fontSize: 46.0,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
)
),
PopupMenuButton<VoidCallback>(
onSelected: (VoidCallback value){
value();
},
icon: Icon(
Icons.more_horiz,
size: 30.0,
color: Colors.white,
),
itemBuilder: (BuildContext context) => <PopupMenuEntry<VoidCallback>>[...],
),
],
),
),
((){
if(dataReady){
PageController controller = PageController(initialPage: sortedNotes.length - 1);
controller.addListener(() {
setState(() {
currentPage = controller.page;
});
});
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
Text("${sortedNotes.length} Entries",
style: TextStyle(color: Colors.tealAccent[200]))
],
),
),
Stack(
children: <Widget>[
CardScrollWidget(currentPage, sortedNotes, largeCards ? 0.8 : 1.2),
Positioned.fill(
child: GestureDetector(
onTap: () {
editNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
onLongPress: () {
deleteNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
child: ScrollConfiguration(
behavior: PageScrollBehavior(),
child: PageView.builder(
itemCount: sortedNotes.length,
controller: controller,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
),
),
)
],
),
],
);
}
else{
return Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SpinKitPulse(
color: Colors.tealAccent,
size: 60.0,
),
),
);
}
}()),
SizedBox(height: 15,),
],
);
}
}
我在未来的构建器中使用 pageview.builder 时遇到问题。它正在分页的项目是卡片,我以前确实有这个工作,但是在实现逻辑来获取笔记和我去使用未来构建器的东西并将这个 NoteSet 移到它自己的 class 中。我想我在某个地方做了重大改变,但我不确定。奇怪的是,我可以构建并查看卡片。封闭的手势检测器也能正常工作,但我无法翻阅 pageview.builder.
非常感谢任何帮助!
class NoteSet extends StatefulWidget {
VoidCallback callback;
final Category category;
NoteSet(this.category, this.callback);
@override
_NoteSetState createState() => _NoteSetState();
}
class _NoteSetState extends State<NoteSet> {
List<NoteEntry> sortedNotes = [];
double currentPage;
bool largeCards = false;
SortMethod currentSortMethod = SortMethod.CreatedDescending;
Future<List<NoteEntry>> getNotes() async {
return await readCategoryNotes(widget.category);
}
void sortNotes(){...}
refresh() {...}
deleteCategory() async {
deleteCategoryDialog(context, widget.category, refresh);
}
void toggleModifiedSort(){
currentSortMethod == SortMethod.ModifiedDescending ? currentSortMethod = SortMethod.ModifiedAscending : currentSortMethod = SortMethod.ModifiedDescending;
refresh();
}
void toggleCreatedSort(){
currentSortMethod == SortMethod.CreatedDescending ? currentSortMethod = SortMethod.CreatedAscending : currentSortMethod = SortMethod.CreatedDescending;
refresh();
}
void toggleCardSize(){
largeCards = !largeCards;
refresh();
}
void moveThisCategoryUp() async {
await moveCategoryUp(widget.category);
refresh();
}
void moveThisCategoryDown() async {
await moveCategoryDown(widget.category);
refresh();
}
@override
Widget build(BuildContext context) {
PageController controller = PageController();
currentPage = (sortedNotes.length - 1).roundToDouble();
return Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(widget.category.toString().split(".").last,
style: TextStyle(
color: Colors.white,
fontSize: 46.0,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
)
),
PopupMenuButton<VoidCallback>(...),
],
),
),
FutureBuilder(
future: getNotes(),
builder: (context, snapshot){
if(snapshot.hasData){
sortedNotes = snapshot.data;
sortNotes();
controller.addListener(() {
setState(() {
currentPage = controller.page;
});
});
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
Text("${sortedNotes.length} Entries",
style: TextStyle(color: Colors.tealAccent[200]))
],
),
),
Stack(
children: <Widget>[
CardScrollWidget(currentPage, sortedNotes, largeCards ? 0.8 : 1.2),
Positioned.fill(
child: GestureDetector(
onTap: () {
editNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
onLongPress: () {
deleteNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
child: ScrollConfiguration(
behavior: PageScrollBehavior(),
child: PageView.builder(
itemCount: sortedNotes.length,
controller: controller,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
),
),
)
],
),
],
);
}
else{
return Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SpinKitPulse(
color: Colors.tealAccent,
size: 60.0,
),
),
);
}
},
),
SizedBox(height: 15,),
],
);
}
}
好的,所以我发现了我的问题,每次构建 NoteSet 时,它都会将 currentPage 变量设置为初始页面。我还删除了 future 构建器,而是在 init 上调用 future,然后在找到数据时刷新。这是我更正的代码:
class NoteSet extends StatefulWidget {
VoidCallback callback;
final Category category;
NoteSet(this.category, this.callback);
@override
_NoteSetState createState() => _NoteSetState();
}
class _NoteSetState extends State<NoteSet> {
List<NoteEntry> sortedNotes = [];
double currentPage = 0;
bool largeCards = false;
bool dataReady = false;
SortMethod currentSortMethod = SortMethod.CreatedDescending;
Future getNotes() async {
dataReady = false;
refresh();
sortedNotes = await readCategoryNotes(widget.category);
currentPage = (sortedNotes.length - 1).roundToDouble();
dataReady = true;
refresh();
}
void sortNotes(){...}
refresh() {
widget.callback();
this.setState((){});
sortNotes();
}
...
@override
void initState() {
getNotes();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(widget.category.toString().split(".").last,
style: TextStyle(
color: Colors.white,
fontSize: 46.0,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
)
),
PopupMenuButton<VoidCallback>(
onSelected: (VoidCallback value){
value();
},
icon: Icon(
Icons.more_horiz,
size: 30.0,
color: Colors.white,
),
itemBuilder: (BuildContext context) => <PopupMenuEntry<VoidCallback>>[...],
),
],
),
),
((){
if(dataReady){
PageController controller = PageController(initialPage: sortedNotes.length - 1);
controller.addListener(() {
setState(() {
currentPage = controller.page;
});
});
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
Text("${sortedNotes.length} Entries",
style: TextStyle(color: Colors.tealAccent[200]))
],
),
),
Stack(
children: <Widget>[
CardScrollWidget(currentPage, sortedNotes, largeCards ? 0.8 : 1.2),
Positioned.fill(
child: GestureDetector(
onTap: () {
editNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
onLongPress: () {
deleteNoteDialog(context, sortedNotes[currentPage.round()], refresh);
},
child: ScrollConfiguration(
behavior: PageScrollBehavior(),
child: PageView.builder(
itemCount: sortedNotes.length,
controller: controller,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
),
),
)
],
),
],
);
}
else{
return Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SpinKitPulse(
color: Colors.tealAccent,
size: 60.0,
),
),
);
}
}()),
SizedBox(height: 15,),
],
);
}
}