创建小部件的状态



我有两个tabA,tabB,它们通过用户点击来切换。

我要做的是

  1. 首先tabA打开
  2. tabB文本根据tabA状态变化。
  3. 用户打开tabB,出现更改的文本。

我的基本想法是通过对象键获取tabB状态。

但是有一个问题,

打开tabB之前,没有创建tabB的状态。

这些是我的源代码tabAplayerPage,tabBsettingPage

class _MainFrameState extends State<MainFrame>{
void _onItemTapped(int index) => setState(() => _selectedIndex = index );
int _selectedIndex = 0;
Widget settingPage = Text("");
Widget playerPage = Text("");
GlobalKey<_PlayerPageState> _playerPageKey = new GlobalKey<_PlayerPageState>();
GlobalKey<_SettingPageState> _settingPageKey = new GlobalKey<_SettingPageState>();

@override
void initState() {
print("Main Frame init state");
super.initState();
playerPage = PlayerPage(key:_playerPageKey);
settingPage = SettingPage(key:_settingPageKey);

}
function whenSomethingChanged(){ //this is called by push button or some user action,so initState() is already called.
print(playerPage.currentState!) // it has state and operatable.
print(settingPage.currentState!)  // I want to change the tabB text but it returns null.
}
@override
Widget build(BuildContext context) {
print("Main Frame build");

List<Widget> _pages = [
playerPage,
settingPage
];
return Scaffold(

appBar: EmptyAppBar(),
body:Container(
decoration: new BoxDecoration(color: Colors.red),
child:Center(child:_pages.elementAt(_selectedIndex),)),

bottomNavigationBar: BottomNavigationBar(
selectedItemColor: Color(0xffC03410),
unselectedItemColor: Color(0xffE96D2F),
backgroundColor: Color(0xffF7BF51),
type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.play_circle),
label: 'Player',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Setting',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
);
}
}

我可以告诉你,当第一次构建称为PlayerPage创建,但SettingPage没有。

但是我想控制SettinPage,在它显示之前。

这个问题的解决方案是什么?

由于您没有说明您想在TabB上显示哪种TabA状态,因此我将假设它是一个String并编写此代码。实现目标的方法有很多,这只是其中之一。

步骤1:像这样将PlayerPage state的值传递给SettingPage:

class SettingPage extends StatefulWidget {
const SettingPage({
Key? key,
required this.text,
}) : super(key: key);
final String text;
@override
_SettingPageState createState() => _SettingPageState();
}
class _SettingPageState extends State<SettingPage> {
@override
Widget build(BuildContext context) {
return Center(child: Text(widget.text));
}
}

步骤2:让我们假设你想在SettingPage上显示的状态是来自TextField。也许是球员的名字。然后,当textField值发生变化时,您需要将其传递给MainFrame()小部件。

class PlayerPage extends StatefulWidget {
const PlayerPage({
Key? key,
required this.onTextChanged,
}) : super(key: key);
final Function(String) onTextChanged;
@override
_PlayerPagetate createState() => _PlayerPagetate();
}
class _PlayerPagetate extends State<PlayerPage> {
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Center(
child: TextField(
controller: _controller,
onChanged: (value) {
widget.onTextChanged(value);
},
),
);
}
}

步骤3:在MainFrame小部件上,现在您从PlayerPlage获得playerName到_playerName变量,并像这样将其传递给SettingPage。当值改变时,_playerName也会改变:

class _MainFrameState extends State<MainFrame> {
void _onItemTapped(int index) => setState(() => _selectedIndex = index);
int _selectedIndex = 0;
String _playerName = '';
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
print("Main Frame build");
List<Widget> _pages = [
PlayerPage(onTextChanged: (value) {
setState(() {
_playerName = value;
});
}),
SettingPage(text: _playerName)
];
return Scaffold(
// rest of the codes are same.
)

由于您的settingPage不在树中,因此您无法真正访问它的状态,因为它没有被创建。

当你在下面的代码中改变你的_selectedIndex时,无论是一个新的settingPage还是playerPage都会被膨胀,所以只要用它所依赖的值创建它,如果有必要的话就监听它。

body:Container(
decoration: new BoxDecoration(color: Colors.red),
child:Center(child:_pages.elementAt(_selectedIndex),)),

由于您正在根据用户在第1页的输入更新屏幕,我包含了一个代码,如果文本字段为空,它将显示一条消息,如果它有值,则值显示在第二页

import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MainFrame(),
);
}
}
class MainFrame extends StatefulWidget {
const MainFrame({key});
@override
State<MainFrame> createState() => _MainFrameState();
}
class _MainFrameState extends State<MainFrame> {
void _onItemTapped(int index) => setState(() {
print(playerPageController.text);
_selectedIndex = index;
});
int _selectedIndex = 0;
late TextEditingController playerPageController;
late Widget settingPage;
late Widget playerPage;
late List<Widget> _pages;
@override
void initState() {
playerPageController = TextEditingController();
print("Main Frame init state");
super.initState();
}

@override
Widget build(BuildContext context) {
settingPage = Text((playerPageController.text.isEmpty)
? "Theres no content here"
: playerPageController.text);
playerPage = Center(
child: TextField(
controller: playerPageController,
autofocus: true,
));
_pages = [playerPage, settingPage];
print("Main Frame build");
return Scaffold(
body: Container(
decoration: new BoxDecoration(color: Colors.red),
child: Center(
child: _pages.elementAt(_selectedIndex),
)),
bottomNavigationBar: BottomNavigationBar(
selectedItemColor: Color(0xffC03410),
unselectedItemColor: Color(0xffE96D2F),
backgroundColor: Color(0xffF7BF51),
type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.play_circle),
label: 'Player',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Setting',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
);
}
}

相关内容

最新更新