Flutter - 如何在传递值的同时从子项更改父项的主体小部件?
Flutter - How to change the body widget of parent, while passing a value, from child?
所以,我有一个“主页”页面,它有脚手架、应用栏、主体和底部导航栏。
正文作为小部件从列表中加载,具体取决于在 bottomNavigationBar 上单击的内容。
我希望能够在当前加载到父主体中的子部件中按下某些东西,并将父部件的主体部件更改为另一个子部件,同时也将值传递给子部件。
可以把它想象成在浏览器的 iframe 中按下 link,只是 iframe 改变了,你可以传递一个像 ?id=12.
这样的值
这是“主页”页面:
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
final List<Widget> _children = [
Page1(),
Page2(),
Page3(),
Page4()
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
TextButton(
onPressed: () {},
child: Text("Log Out", style: TextStyle(color: Colors.white)),
),
],
backgroundColor: Colors.blue.shade900,
),
body: _children[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.work),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.inventory),
label: 'Page 2',
),
BottomNavigationBarItem(
icon: Icon(Icons.alt_route),
label: 'Page 3',
),
BottomNavigationBarItem(
icon: Icon(Icons.article),
label: 'Page 4',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
type: BottomNavigationBarType.fixed,
),
);
}
}
这是将由 _children[_selectedIndex] 通过按下 bottomNavigationBar
中的按钮之一定义的子窗口小部件
class Page1 extends StatefulWidget {
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
@override
Widget build(BuildContext context) {
return Text("Click Here",onPressed:(){
//objective here is to open Page5 in the body of HomePage(not in _children list of homepage, and pass it some value (ie. id 12))
},
),
);
}
}
为了举例说明期望,这是我想要在 Page5 中的内容(应该加载到主页的正文中
class Page5 extends StatefulWidget {
@override
_Page5State createState() => _Page5State();
}
class _Page5State extends State<Page5> {
int _variableFromPage1;
@override
Widget build(BuildContext context) {
return Text(_variableFromPage1);
}
}
任何人都可以建议最好的方法吗?
你这样试试
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
// This widget is the root of your application.
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _selectedIndex = 0;
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case "Home":
return MaterialPageRoute(builder: (context) => Home());
case "Settings":
return MaterialPageRoute(builder: (context) => Settings());
default:
return MaterialPageRoute(builder: (context) => Default());
}
}
void _onItemTapped(int index) {
switch (index) {
case 1:
_navigatorKey.currentState!
.pushNamedAndRemoveUntil("Home", (route) => false);
break;
case 2:
_navigatorKey.currentState!
.pushNamedAndRemoveUntil("Settings", (route) => false);
break;
default:
_navigatorKey.currentState!
.pushNamedAndRemoveUntil("Default", (route) => false);
}
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Navigator(key: _navigatorKey, onGenerateRoute: generateRoute),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Setting',
),
],
showSelectedLabels: true,
showUnselectedLabels: false,
currentIndex: _selectedIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Color(0xFF9e9e9e),
iconSize: 16,
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
onTap: _onItemTapped,
),
),
);
}
}
您可以像下面的代码示例一样定义自定义回调函数。
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
int _selectedID = 0;
List<Widget> _children;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
void initState() {
super.initState();
_children = [
Page1(
callback: (value) {
setState(() {
_selectedID = value;
});
},
),
Page2(),
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: (_selectedIndex == 0 && _selectedID > 0)
? Page5(id: _selectedID)
: _children[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.work),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.inventory),
label: 'Page 2',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
type: BottomNavigationBarType.fixed,
),
);
}
}
typedef IntCallback(int value);
class Page1 extends StatelessWidget {
Page1({Key key, @required this.callback}) : super(key: key);
final IntCallback callback;
@override
Widget build(BuildContext context) {
return Center(
child: InkWell(
onTap: () {
callback(12);
},
child: Text("Page1 ::: id >>> 12"),
),
);
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text("Page2"),
);
}
}
class Page5 extends StatelessWidget {
Page5({Key key, @required this.id}) : super(key: key);
final int id;
@override
Widget build(BuildContext context) {
return Center(child: Text("Page5 ::: id $id"));
}
}
所以,我有一个“主页”页面,它有脚手架、应用栏、主体和底部导航栏。 正文作为小部件从列表中加载,具体取决于在 bottomNavigationBar 上单击的内容。 我希望能够在当前加载到父主体中的子部件中按下某些东西,并将父部件的主体部件更改为另一个子部件,同时也将值传递给子部件。 可以把它想象成在浏览器的 iframe 中按下 link,只是 iframe 改变了,你可以传递一个像 ?id=12.
这样的值这是“主页”页面:
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
final List<Widget> _children = [
Page1(),
Page2(),
Page3(),
Page4()
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
TextButton(
onPressed: () {},
child: Text("Log Out", style: TextStyle(color: Colors.white)),
),
],
backgroundColor: Colors.blue.shade900,
),
body: _children[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.work),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.inventory),
label: 'Page 2',
),
BottomNavigationBarItem(
icon: Icon(Icons.alt_route),
label: 'Page 3',
),
BottomNavigationBarItem(
icon: Icon(Icons.article),
label: 'Page 4',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
type: BottomNavigationBarType.fixed,
),
);
}
}
这是将由 _children[_selectedIndex] 通过按下 bottomNavigationBar
中的按钮之一定义的子窗口小部件class Page1 extends StatefulWidget {
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
@override
Widget build(BuildContext context) {
return Text("Click Here",onPressed:(){
//objective here is to open Page5 in the body of HomePage(not in _children list of homepage, and pass it some value (ie. id 12))
},
),
);
}
}
为了举例说明期望,这是我想要在 Page5 中的内容(应该加载到主页的正文中
class Page5 extends StatefulWidget {
@override
_Page5State createState() => _Page5State();
}
class _Page5State extends State<Page5> {
int _variableFromPage1;
@override
Widget build(BuildContext context) {
return Text(_variableFromPage1);
}
}
任何人都可以建议最好的方法吗?
你这样试试
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
// This widget is the root of your application.
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _selectedIndex = 0;
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case "Home":
return MaterialPageRoute(builder: (context) => Home());
case "Settings":
return MaterialPageRoute(builder: (context) => Settings());
default:
return MaterialPageRoute(builder: (context) => Default());
}
}
void _onItemTapped(int index) {
switch (index) {
case 1:
_navigatorKey.currentState!
.pushNamedAndRemoveUntil("Home", (route) => false);
break;
case 2:
_navigatorKey.currentState!
.pushNamedAndRemoveUntil("Settings", (route) => false);
break;
default:
_navigatorKey.currentState!
.pushNamedAndRemoveUntil("Default", (route) => false);
}
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Navigator(key: _navigatorKey, onGenerateRoute: generateRoute),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Setting',
),
],
showSelectedLabels: true,
showUnselectedLabels: false,
currentIndex: _selectedIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Color(0xFF9e9e9e),
iconSize: 16,
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
onTap: _onItemTapped,
),
),
);
}
}
您可以像下面的代码示例一样定义自定义回调函数。
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
int _selectedID = 0;
List<Widget> _children;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
void initState() {
super.initState();
_children = [
Page1(
callback: (value) {
setState(() {
_selectedID = value;
});
},
),
Page2(),
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: (_selectedIndex == 0 && _selectedID > 0)
? Page5(id: _selectedID)
: _children[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.work),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.inventory),
label: 'Page 2',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
type: BottomNavigationBarType.fixed,
),
);
}
}
typedef IntCallback(int value);
class Page1 extends StatelessWidget {
Page1({Key key, @required this.callback}) : super(key: key);
final IntCallback callback;
@override
Widget build(BuildContext context) {
return Center(
child: InkWell(
onTap: () {
callback(12);
},
child: Text("Page1 ::: id >>> 12"),
),
);
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text("Page2"),
);
}
}
class Page5 extends StatelessWidget {
Page5({Key key, @required this.id}) : super(key: key);
final int id;
@override
Widget build(BuildContext context) {
return Center(child: Text("Page5 ::: id $id"));
}
}