簡體   English   中英

Flutter - 可聚焦的 ListView 項目

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM