Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振-可聚焦的ListView项_Flutter_Dart - Fatal编程技术网

Flutter 颤振-可聚焦的ListView项

Flutter 颤振-可聚焦的ListView项,flutter,dart,Flutter,Dart,我是新加入颤振的,最近我在颤振中使用ListView Builder和FocusNode,我想要一个小部件列表,一次只能选择一个,最初它工作正常,但当有一个长列表时(以7项为例),当我单击第一个项目并转到列表中的最后一个项目时,第一个小部件被停用并重建小部件,最终使其未被选中 这是列表视图生成器 ListView.builder( itemCount: appliances.length, scrollDirection: Axis.horizontal, itemBuilder: (co

我是新加入颤振的,最近我在颤振中使用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,
              ),
            ),
          ],
        ),
      ),
    ),
  ),
);
class\u应用程序状态扩展{
FocusNode_节点;
以布尔为中心;
聚焦附件;
@凌驾
void initState(){
super.initState();
_node=FocusNode(debugLabel:'按钮');
_聚焦=_node.hasFocus;
_node.addListener(_handleFocusChange);
_nodeAttachment=_node.attach(上下文);
}
void_handleFocusChange(){
如果(\u node.hasFocus!=\u focused){
设置状态(){
_聚焦=_node.hasFocus;
});
}
}
@凌驾
小部件构建(构建上下文){
_nodeAttachment.reparent();
返回容器(
填充:边缘组。对称(水平:10.0,垂直:10.0),
高度:ScreenUtil().setHeight(120),
宽度:ScreenUtil().setWidth(300),
儿童:材料(
颜色:颜色。透明,
孩子:InkWell(
onTap:(){
如果(_聚焦){
_node.unfocus();
widget.onChanged('null');
}否则{
_requestFocus();
onChanged(widget.appliancesData.name);
}
},
子:容器(
填充:边缘组。对称(水平:10.0),
装饰:盒子装饰(
颜色:_聚焦?AppTheme.appPrimary:AppTheme.white,
边界半径:边界半径。圆形(5.0),
boxShadow:[
箱形阴影(
颜色:颜色。黑色。不透明度(0.6),
偏移量:偏移量(0.2,0.2),
半径:0.9),
],
),
子:列(
mainAxisAlignment:mainAxisAlignment.space,
儿童:[
填充物(
填充:所有边缘设置(2.0),
子:Image.asset(
widget.appliancesData.icon,
颜色:_聚焦?AppTheme.white:AppTheme.nearlyBlack,
宽度:ScreenUtil().setWidth(65),
),
),
填充物(
填充:所有边缘设置(2.0),
子项:文本(widget.appliancesData.name,
样式:_聚焦?已选择:未选择),
),
填充物(
填充:所有边缘设置(2.0),
子:文本(
‘20千瓦’,
样式:\聚焦?选中:未选中,
),
),
],
),
),
),
),
);

IMHO,滚动列表时,
\u变量始终重置为默认值

将子对象从视图中滚出时,关联的 元素子树、状态和渲染对象被销毁。新的子元素 在列表中的相同位置,将随 向后滚动时的新元素、状态和渲染对象

您可以尝试以下操作:(将
\u focused
状态移动到父级)

class SamplePage扩展StatefulWidget{
SamplePage({Key}):super(Key:Key);
@凌驾
State createState()=>SamplePageState();
}
类SamplePageState扩展状态{
列表项=列表();
@凌驾
void initState(){
super.initState();
项目。添加([“项目00”,“选定”]);
项目。添加([“项目01”,“项目]);
项目。添加([“项目02”,“项目]);
项目。添加([“项目03”,“项目]);
项目。添加([“项目04”,“项目]);
项目。添加([“项目05”,“项目]);
项目。添加([“项目06”,“项目]);
项目。添加([“项目07”,“项目]);
项目。添加([“项目08”,”);
项目。添加([“项目09”,“项目]);
项目。添加([“项目10”,“项目]);
项目。添加([“项目11”,“项目]);
添加([“第12项”,”);
添加([“第13项”,”);
项目。添加([“项目14”,”);
项目。添加([“项目15”,“项目]);
添加([“第16项”,”);
项目。添加([“项目17”,”);
项目。添加([“项目18”,”);
项目。添加([“项目19”,”);
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
主体:容器(
身高:600,
子项:ListView.builder(
itemCount:items.length,
itemBuilder:(上下文,索引){
返回手势检测器(
行为:HitTestBehavior.不透明,
子:容器(
身高:80,
颜色:项目[索引][1]=“选定”?颜色。浅蓝色:颜色。白色,
子项:文本(项[索引][0]),
),
onTap:(){
用于(项目中的最终项目){
如果(项目[1]=“选定”)项目[1]=“选定”;
}
设置状态(()=>items[index][1]='selected');
},
);
}
),
),
);
}
}

你能分享你的代码片段吗?我已经编辑了这个问题,并在那里添加了代码片段@Ayushbherwani,如果我有太长的列表(比如1000个项目),这不会在加载时产生问题@Hianit不会…
ListView
不会一次创建1000个项目…仅在屏幕上显示项目。ListView.builder构造函数采用IndexedWidgetBuilder,可根据需要生成子项。此构造函数适用于具有大(或无限)值的列表视图子对象数,因为仅为实际可见的子对象调用生成器---
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');
                            },
                        );
                    }
                ),
            ),
        );
    }

}