我有一个父窗口小部件,其中包含项目列表和所选项目的索引。子窗口小部件告诉父项何时选择了一项。如果我将isSelected(index)函数传递给子窗口小部件,则子窗口小部件将更新以显示选择了哪个项目。如果我将selectedIndex int传递给子窗口小部件,则selectedIndex在父级而不是子级中更新。
使用isSelected(index)函数的工作版本
import 'package:flutter/material.dart';
class IsSelected extends StatefulWidget {
@override
State<StatefulWidget> createState() => IsSelectedState();
}
class IsSelectedState extends State<IsSelected> {
List<int> _items = List.from([0]);
int _selectedIndex = -1;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.indeterminate_check_box),
onPressed: () {
setState(() {
_items.removeAt(_selectedIndex);
});
}
),
IconButton(
icon: Icon(Icons.add_box),
onPressed: () {
setState(() {
_items.add(_items.length);
});
}
)
]
),
Expanded(
child: ItemList(
items: _items,
isSelected: (index) => _selectedIndex == index,
onSelect: (index) => setState(() {
_selectedIndex = index;
})
)
)
],
)
);
}
}
class ItemList extends StatefulWidget {
final List<int> _items;
final Function _isSelected;
final Function _onSelect;
ItemList({items, isSelected, onSelect}) :
_items = items,
_isSelected = isSelected,
_onSelect = onSelect;
@override
State<StatefulWidget> createState() => ItemListState(
items: _items,
isSelected: _isSelected,
onSelect: _onSelect
);
}
class ItemListState extends State<ItemList> {
final List<int> _items;
final Function _isSelected;
final Function _onSelect;
ItemListState({items, isSelected, onSelect}) :
_items = items,
_isSelected = isSelected,
_onSelect = onSelect;
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _items.length,
itemBuilder: (BuildContext context, int index) {
// I used a withOpacity(0) below to make the border transparent
// The background colors of the ListView isn't quite white
final Color borderColor = _isSelected(index) ?
Theme.of(context).primaryColor : Colors.white.withOpacity(0);
return GestureDetector(
onTap: () => _onSelect(index),
child: Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
decoration: BoxDecoration(
border: Border.all(
color: borderColor,
width: 2
)
),
child: Row(
children: <Widget> [
Expanded(
child: Text(_items[index].toString(),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
)
)
]
)
)
);
},
);
}
}
非工作版本,将selectedIndex传递给子窗口小部件
import 'package:flutter/material.dart';
class SelectedIndex extends StatefulWidget {
@override
State<StatefulWidget> createState() => SelectedIndexState();
}
class SelectedIndexState extends State<SelectedIndex> {
List<int> _items = List.from([0]);
int _selectedIndex = -1;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.indeterminate_check_box),
onPressed: () {
setState(() {
_items.removeAt(_selectedIndex);
});
}
),
IconButton(
icon: Icon(Icons.add_box),
onPressed: () {
setState(() {
_items.add(_items.length);
});
}
)
]
),
Expanded(
child: ItemList(
items: _items,
selectedIndex: _selectedIndex,
onSelect: (index) => setState(() {
_selectedIndex = index;
})
)
)
],
)
);
}
}
class ItemList extends StatefulWidget {
final List<int> _items;
final int _selectedIndex;
final Function _onSelect;
ItemList({items, selectedIndex, onSelect}) :
_items = items,
_selectedIndex = selectedIndex,
_onSelect = onSelect;
@override
State<StatefulWidget> createState() => ItemListState(
items: _items,
selectedIndex: _selectedIndex,
onSelect: _onSelect
);
}
class ItemListState extends State<ItemList> {
final List<int> _items;
final int _selectedIndex;
final Function _onSelect;
ItemListState({items, selectedIndex, onSelect}) :
_items = items,
_selectedIndex = selectedIndex,
_onSelect = onSelect;
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _items.length,
itemBuilder: (BuildContext context, int index) {
// I used a withOpacity(0) below to make the border transparent
// The background colors of the ListView isn't quite white
final Color borderColor = _selectedIndex == index ?
Theme.of(context).primaryColor : Colors.white.withOpacity(0);
return GestureDetector(
onTap: () => _onSelect(index),
child: Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
decoration: BoxDecoration(
border: Border.all(
color: borderColor,
width: 2
)
),
child: Row(
children: <Widget> [
Expanded(
child: Text(_items[index].toString(),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
)
)
]
)
)
);
},
);
}
}
我了解在第一个版本中,传递给子窗口小部件的功能永远不会改变。这就是为什么我没有问题显示选择哪个项目的原因。有人能够帮助我理解第二个示例所缺少的内容。为什么flutter不更新子窗口小部件中的selectedIndex?使用调试器,我可以看到在更新selectedIndex时重建了子窗口小部件,但是子窗口小部件中的值保持不变。我来自React,在这里我需要做的就是更新道具。这不是Flutter的工作原理吗?