Flutter - 在同一屏幕上的小部件之间传递数据
Flutter - Passing data between widgets on same screen
我将一个屏幕分成两半。上半部分有一个列表视图,底部将根据上面列表视图中的 listTile 中的 onTap: 显示详细信息。
删除所有不相关的部分后,我的代码看起来像这样:
return Scaffold(
appBar: AppBar(
...
// app bar details
...
), // AppBar
body: SingleChildScrollView (
child: Column(
children: <Widget>[
...
Container(
...
child: populatelistview();
),
SizedBox(height: ...),
...
...
Container(
...
child: detailsView();
),
...
],
), // Column
) // SingleChildScrollView
因此,为了让 detailsView 填充基于来自 listview 的 onTap() 的数据,我必须将一些变量(或一些 id)从 listview 传递到 detailsView。
我以前用过Navigator.push(参考:https://flutter.dev/docs/cookbook/navigation/passing-data),但只有在从一个屏幕移动到另一个屏幕时才有效。我无法在同一屏幕上将数据从 listview 发送到 detailsView。
可能是我的看法不同,或者只是无法正确搜索。
如果有人能指出正确的方向,我将不胜感激。
如果之前已经回答了这个问题,那么我对此深表歉意 - 请将其标记为重复并指出正确的讨论。
提前致谢。
注意安全!!
我建议您使用提供者状态管理,这将很容易实现,您的两个视图都会有一些 ChangeNotifier,这里有一些可能对您有帮助的片段:
填充列表视图:
GestureDetector(
onTap: (){
notifier.setId(id);
},
child:// your child
详情查看:
Container(
child: Text(notifier.id),
)
更改通知程序
class Notifier extends ChangeNotifier {
int id;
void setId(int id){
this.id = id;
notifyListeners();// Here the magic happens
}
你可以这样传递信息。在您的 class 中使用一个变量来存储点击项目的信息。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: MyWidget(),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int _item;
@override
void initState() {
super.initState();
_item = null;
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, i) {
return ListTile(
title: Text('Item $i'),
onTap: () => setState(() => _item = i),
);
}),
),
Container(height: 2, color: Colors.grey),
Expanded(
child: Container(
color: Colors.grey[100],
child: Center(
child: Text(_item == null
? 'Select an item'
: 'Item $_item was selected',),
),
),
),
]);
}
}
希望对您有所帮助!
如果这是 stateful
小部件,请尝试使用 setState()
参见下面的示例代码:
class Test extends State<StatusPage> {
String text = 'Hello';
@override
Widget build(BuildContext context) {
Widget details = Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(text),
],
);
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
itemCount: 4,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('Item #$index'),
onTap: () {
setState(() {
text == 'Hello' ? text = 'Test' : text = 'Hello';
});
},
);
},
),
SizedBox(height: 54),
details,
],
), // Column
),
);
}
}
感谢所有尝试帮助我的人。
但是,我现在已经通过使用 Inherited Widget 解决了这个问题。
Inherited Widget 更适合我需要在不改变屏幕的情况下将数据从一个小部件传输到另一个小部件的情况。
我将一个屏幕分成两半。上半部分有一个列表视图,底部将根据上面列表视图中的 listTile 中的 onTap: 显示详细信息。
删除所有不相关的部分后,我的代码看起来像这样:
return Scaffold(
appBar: AppBar(
...
// app bar details
...
), // AppBar
body: SingleChildScrollView (
child: Column(
children: <Widget>[
...
Container(
...
child: populatelistview();
),
SizedBox(height: ...),
...
...
Container(
...
child: detailsView();
),
...
],
), // Column
) // SingleChildScrollView
因此,为了让 detailsView 填充基于来自 listview 的 onTap() 的数据,我必须将一些变量(或一些 id)从 listview 传递到 detailsView。
我以前用过Navigator.push(参考:https://flutter.dev/docs/cookbook/navigation/passing-data),但只有在从一个屏幕移动到另一个屏幕时才有效。我无法在同一屏幕上将数据从 listview 发送到 detailsView。
可能是我的看法不同,或者只是无法正确搜索。
如果有人能指出正确的方向,我将不胜感激。
如果之前已经回答了这个问题,那么我对此深表歉意 - 请将其标记为重复并指出正确的讨论。
提前致谢。
注意安全!!
我建议您使用提供者状态管理,这将很容易实现,您的两个视图都会有一些 ChangeNotifier,这里有一些可能对您有帮助的片段:
填充列表视图:
GestureDetector(
onTap: (){
notifier.setId(id);
},
child:// your child
详情查看:
Container(
child: Text(notifier.id),
)
更改通知程序
class Notifier extends ChangeNotifier {
int id;
void setId(int id){
this.id = id;
notifyListeners();// Here the magic happens
}
你可以这样传递信息。在您的 class 中使用一个变量来存储点击项目的信息。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: MyWidget(),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int _item;
@override
void initState() {
super.initState();
_item = null;
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, i) {
return ListTile(
title: Text('Item $i'),
onTap: () => setState(() => _item = i),
);
}),
),
Container(height: 2, color: Colors.grey),
Expanded(
child: Container(
color: Colors.grey[100],
child: Center(
child: Text(_item == null
? 'Select an item'
: 'Item $_item was selected',),
),
),
),
]);
}
}
希望对您有所帮助!
如果这是 stateful
小部件,请尝试使用 setState()
参见下面的示例代码:
class Test extends State<StatusPage> {
String text = 'Hello';
@override
Widget build(BuildContext context) {
Widget details = Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(text),
],
);
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
itemCount: 4,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('Item #$index'),
onTap: () {
setState(() {
text == 'Hello' ? text = 'Test' : text = 'Hello';
});
},
);
},
),
SizedBox(height: 54),
details,
],
), // Column
),
);
}
}
感谢所有尝试帮助我的人。 但是,我现在已经通过使用 Inherited Widget 解决了这个问题。
Inherited Widget 更适合我需要在不改变屏幕的情况下将数据从一个小部件传输到另一个小部件的情况。