[英]Flutter - Focusable ListView items
我最近是 flutter 新手,我在 Flutter 中使用 ListView Builder 和 FocusNode,我想要一個小部件列表,一次只能選擇一個,最初它工作正常,但是當列表很長時(取 7 個項目),當我單擊第一個項目並轉到列表中的最后一個項目,第一個小部件被停用並重建小部件,最終使其未被選中。
這是列表視圖構建器
ListView.builder(
itemCount: appliances.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return ApplicancesTile(
appliancesData: appliances[index],
onChanged: (value){
setState(() {
selected = value;
});
},
);
},
),
這是小部件
class _ApplicancesTileState extends State<ApplicancesTile> {
FocusNode _node;
bool _focused;
FocusAttachment _nodeAttachment;
@override
void initState() {
super.initState();
_node = FocusNode(debugLabel: 'Button');
_focused = _node.hasFocus;
_node.addListener(_handleFocusChange);
_nodeAttachment = _node.attach(context);
}
void _handleFocusChange() {
if (_node.hasFocus != _focused) {
setState(() {
_focused = _node.hasFocus;
});
}
}
@override
Widget build(BuildContext context) {
_nodeAttachment.reparent();
return Container(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
height: ScreenUtil().setHeight(120),
width: ScreenUtil().setWidth(300),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
if (_focused) {
_node.unfocus();
widget.onChanged('null');
} else {
_node.requestFocus();
widget.onChanged(widget.appliancesData.name);
}
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.0),
decoration: BoxDecoration(
color: _focused ? AppTheme.appPrimary : AppTheme.white,
borderRadius: BorderRadius.circular(5.0),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black.withOpacity(0.6),
offset: Offset(0.2, 0.2),
blurRadius: 0.9),
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: EdgeInsets.all(2.0),
child: Image.asset(
widget.appliancesData.icon,
color: _focused ? AppTheme.white : AppTheme.nearlyBlack,
width: ScreenUtil().setWidth(65),
),
),
Padding(
padding: EdgeInsets.all(2.0),
child: Text(widget.appliancesData.name,
style: _focused ? selected : notSelected),
),
Padding(
padding: EdgeInsets.all(2.0),
child: Text(
'20 kW',
style: _focused ? selected : notSelected,
),
),
],
),
),
),
),
);
恕我直言,當您滾動列表時,您的_focused
變量始終重置為默認值。
當子元素滾出視圖時,關聯的元素子樹、狀態和渲染對象將被銷毀。 當向后滾動時,列表中相同位置的新子項將與新元素、狀態和渲染對象一起懶惰地重新創建。
你可以試試這個:(將_focused
狀態移動到父級)
class SamplePage extends StatefulWidget {
SamplePage({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => SamplePageState();
}
class SamplePageState extends State<SamplePage> {
List<List<String>> items = List();
@override
void initState() {
super.initState();
items.add(["Item 00", "selected"]);
items.add(["Item 01", ""]);
items.add(["Item 02", ""]);
items.add(["Item 03", ""]);
items.add(["Item 04", ""]);
items.add(["Item 05", ""]);
items.add(["Item 06", ""]);
items.add(["Item 07", ""]);
items.add(["Item 08", ""]);
items.add(["Item 09", ""]);
items.add(["Item 10", ""]);
items.add(["Item 11", ""]);
items.add(["Item 12", ""]);
items.add(["Item 13", ""]);
items.add(["Item 14", ""]);
items.add(["Item 15", ""]);
items.add(["Item 16", ""]);
items.add(["Item 17", ""]);
items.add(["Item 18", ""]);
items.add(["Item 19", ""]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 600,
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
child: Container(
height: 80,
color: items[index][1] == "selected" ? Colors.lightBlue : Colors.white,
child: Text(items[index][0]),
),
onTap: () {
for (final item in items) {
if (item[1] == 'selected') item[1] = '';
}
setState(() => items[index][1] = 'selected');
},
);
}
),
),
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.