Flutter 如何在ListView中放置键以保持页面更改状态

Flutter 如何在ListView中放置键以保持页面更改状态,flutter,flutter-layout,Flutter,Flutter Layout,我正在尝试建立一个用户可以滚动浏览的帖子流(想想twitter或instagram类型的帖子)。当他们滚动时,他们可以单击其中一篇文章并导航到新页面。当它们从该页面返回时,我希望它们保持在与以前在ListView中的位置相同的位置 问题 我目前无法阻止流小部件重建并返回滚动位置。我知道解决这一问题的方法之一是包含一个密钥;但是,我尝试在ListView.builder中包含该键,但没有成功 问题 我应该把钥匙放在哪里?我使用的钥匙类型正确吗 类流扩展StatefulWidget{ 流({Key

我正在尝试建立一个用户可以滚动浏览的帖子流(想想twitter或instagram类型的帖子)。当他们滚动时,他们可以单击其中一篇文章并导航到新页面。当它们从该页面返回时,我希望它们保持在与以前在ListView中的位置相同的位置

问题

我目前无法阻止流小部件重建并返回滚动位置。我知道解决这一问题的方法之一是包含一个密钥;但是,我尝试在ListView.builder中包含该键,但没有成功

问题 我应该把钥匙放在哪里?我使用的钥匙类型正确吗

类流扩展StatefulWidget{
流({Key-Key,this.user}):超级(Key:Key);
最终用户;
@凌驾
_StreamState createState()=>new\u StreamState(
用户:用户
);
}
类_StreamState扩展了状态{
_StreamState({this.user});
最终用户;
Firestore _Firestore=Firestore.instance;
列表_posts=[];
bool_loadingPosts=真;
每页整数=30;
文档快照_lastPosts;
ScrollController_ScrollController=ScrollController();
bool_gettingMorePosts=false;
bool\u morePostsAvailable=true;
_getPosts()异步{
查询q=\u firestore
.collection(“posts”)
.document(user.user\u id)
.collection(“posts”)
.orderBy(“时间公告”,降序:true)
.限制(每页);
设置状态(){
_loadingPosts=true;
});
QuerySnapshot QuerySnapshot=wait q.getDocuments();
_posts=querySnapshot.documents;
如果(_posts.length==0){
设置状态(){
_装货柱=假;
});
}
否则{
_lastPosts=querySnapshot.documents[querySnapshot.documents.length-1];
设置状态(){
_装货柱=假;
});
}
}
_getMorePosts()异步{
if(_morespostsavailable==false){
回来
}
if(_gettingMorePosts==true){
回来
}
如果(_posts.length==0){
回来
}
_gettingMorePosts=true;
查询q=\u firestore
.collection(“posts”)
.document(user.user\u id)
.collection(“posts”)
.orderBy(“时间公告”,降序:true)
.startAfter([\u lastPosts.data['timePosted']])。限制(\u每页);
QuerySnapshot QuerySnapshot=wait q.getDocuments();
if(querySnapshot.documents.length==0){
_morePostsAvailable=false;
}
如果(querySnapshot.documents.length>0){
_lastPosts=querySnapshot.documents[querySnapshot.documents.length-1];
}
_posts.addAll(querySnapshot.documents);
setState((){});
_gettingMorePosts=false;
}
@凌驾
void initState(){
super.initState();
_getPosts();
_scrollController.addListener((){
double maxScroll=\u scrollController.position.maxScrollExtent;
双currentScroll=\u scrollController.position.pixels;
double delta=MediaQuery.of(context).size.height*0.25;
如果(maxScroll-currentScroll<增量){
_getMorePosts();
}
});
}
@凌驾
小部件构建(构建上下文){
返回列(
儿童:[
新扩展(
子项:_loadingPosts==true
?容器(
儿童:中心(
子项:文本(“”),
),
)
:容器(
儿童:中心(
子项:_posts.length==0
?中心(
子项:文本(“跟随朋友”,样式:TextStyle(fontSize:15),),
)
:ListView.builder(
key:widget.key,
控制器:\ u滚动控制器,
itemCount:_posts.length,
itemBuilder:(BuildContext ctx,int索引){
返回新部件(
//用于在此处构建post小部件的参数
);
}),
),
),
),
],
);

}
这类关键功能:

key: PageStorageKey('Your Key Name'),

这类关键工作:

key: PageStorageKey('Your Key Name'),

简短回答:

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: ListView.builder(
        key: PageStorageKey("any_text_here"), // this is the key you need
        itemCount: 50,
        itemBuilder: (_, i) {
          return ListTile(
            title: Text("Item ${i}"),
            onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => DetailPage(index: i))),
          );
        },
      ),
    );
  }
}

class DetailPage extends StatefulWidget {
  final int index;

  const DetailPage({Key key, this.index}) : super(key: key);

  @override
  _DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Text(
          "You clicked ${widget.index}",
          style: Theme.of(context).textTheme.headline,
        ),
      ),
    );
  }
}
您需要提供
ListView.builder
的密钥,如下所示:

ListView.builder(
  key: PageStorageKey("any_text_here"),
  // ...
)

长答案:

您可以看到,当您从屏幕2返回到屏幕1时,项目30保留在顶部


很抱歉,由于您所使用的变量的可用性有限,很难重现您的代码。我创建了一个简单的示例来演示您所寻找的内容

完整代码:

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: ListView.builder(
        key: PageStorageKey("any_text_here"), // this is the key you need
        itemCount: 50,
        itemBuilder: (_, i) {
          return ListTile(
            title: Text("Item ${i}"),
            onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => DetailPage(index: i))),
          );
        },
      ),
    );
  }
}

class DetailPage extends StatefulWidget {
  final int index;

  const DetailPage({Key key, this.index}) : super(key: key);

  @override
  _DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Text(
          "You clicked ${widget.index}",
          style: Theme.of(context).textTheme.headline,
        ),
      ),
    );
  }
}
void main()=>runApp(MaterialApp(home:HomePage());
类主页扩展了StatefulWidget{
@凌驾
_HomePageState createState()=>\u HomePageState();
}
类_HomePageState扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(),
正文:ListView.builder(
key:PageStorageKey(“此处的任意文本”),//这是您需要的密钥
物品计数:50,
itemBuilder:(u,i){
返回列表块(
标题:文本(“项目${i}”),
onTap:()=>Navigator.push(上下文,materialpage(生成器:()=>DetailPage(索引:i)),
);
},
),
);
}
}
类DetailPage扩展StatefulWidget{
最终整数指数;
constdetailpage({Key,this.index}):super(Key:Key);
@凌驾
_DetailPageState createState()=>\u DetailPageState();
}
类_DetailPageState扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(),
正文:中(
子:文本(
“您单击了${widget.index}”,
风格:Theme.of(context).textTheme.headline,
),
),
);
}
}

简短回答:

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: ListView.builder(
        key: PageStorageKey("any_text_here"), // this is the key you need
        itemCount: 50,
        itemBuilder: (_, i) {
          return ListTile(
            title: Text("Item ${i}"),
            onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => DetailPage(index: i))),
          );
        },
      ),
    );
  }
}

class DetailPage extends StatefulWidget {
  final int index;

  const DetailPage({Key key, this.index}) : super(key: key);

  @override
  _DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Text(
          "You clicked ${widget.index}",
          style: Theme.of(context).textTheme.headline,
        ),
      ),
    );
  }
}
您需要像这样提供
ListView.builder
的密钥