在ListtTile水龙头上使行可见

时间:2020-07-13 05:48:29

标签: flutter flutter-layout

我有一个ListView.builder,带有一个Column子级以及该Column的ListTile和Row子级。我想要实现的是,当用户点击ListTile项时,它将使Row可见。如何获得单击的ListTile项,并可以看到连接到该行的行?

代码如下:

class DebitInvoiceLineList extends StatefulWidget {
  
  final List<DebitInvoiceLine> dInvoiceLines;

  DebitInvoiceLineList({
    @required
    
    this.dInvoiceLines
  });

  @override
  _DebitInvoiceLineListState createState() => _DebitInvoiceLineListState();
}

class _DebitInvoiceLineListState extends State<DebitInvoiceLineList> {
  bool visibleEdit = false;

  _changed(bool visibility) {
    setState(() {
      visibleEdit = visibility;
    });
  }

  @override
  Widget build(BuildContext context) {


    return NotificationListener<OverscrollIndicatorNotification>(
      onNotification: (OverscrollIndicatorNotification overScroll) {
        overScroll.disallowGlow();
        return false;
      },
      
      child: ListView.builder(
          
          itemCount: widget.dInvoiceLines.length,
          shrinkWrap: true,
          
          itemBuilder: (context, int index) {
            return Column(
              children: <Widget>[
                ListTile(
                  key: Key(index.toString()),
                  leading: Padding(
                    padding: const EdgeInsets.only(top: 5.0),
                    child: Text(
                      (index + 1).toString() + " - "
                    ),
                  ),
                  title: Text(widget.dInvoiceLines[index].description),
                  trailing: Text(
                      NumberFormat.currency(locale: 'da').format(widget.dInvoiceLines[index].price),
                      style: dSecondHeaderStyle
                  ),
                  onTap: () {
                    setState(() {
                      visibleEdit = !visibleEdit;
                    });
                  }
                ),
                Visibility(
                  visible: visibleEdit,
                  key: Key(index.toString()),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text("Edit"),
                      Text("Delete")
                    ],
                  ),
                )
              ],
            );
            
          },
        ),
      
    );

我可以通过按键进行操作还是如何获取正确的物品?

3 个答案:

答案 0 :(得分:1)

利用 ExpansionTile 小部件,在扑朔迷离中,我们使用ExpansionTile实现了这一功能。

检查示例代码:


import 'package:flutter/material.dart';

class ExpansionTileSample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('ExpansionTile'),
        ),
        body: ListView.builder(
          itemBuilder: (BuildContext context, int index) =>
              EntryItem(data[index]),
          itemCount: data.length,
        ),
      ),
    );
  }
}

// One entry in the multilevel list displayed by this app.
class Entry {
  Entry(this.title, [this.children = const <Entry>[]]);

  final String title;
  final List<Entry> children;
}

// The entire multilevel list displayed by this app.
final List<Entry> data = <Entry>[
  Entry(
    'Chapter A',
    <Entry>[
      Entry(
        'Section A0',
        <Entry>[
          Entry('Item A0.1'),
          Entry('Item A0.2'),
          Entry('Item A0.3'),
        ],
      ),
      Entry('Section A1'),
      Entry('Section A2'),
    ],
  ),
  Entry(
    'Chapter B',
    <Entry>[
      Entry('Section B0'),
      Entry('Section B1'),
    ],
  ),
  Entry(
    'Chapter C',
    <Entry>[
      Entry('Section C0'),
      Entry('Section C1'),
      Entry(
        'Section C2',
        <Entry>[
          Entry('Item C2.0'),
          Entry('Item C2.1'),
          Entry('Item C2.2'),
          Entry('Item C2.3'),
        ],
      ),
    ],
  ),
];

// Displays one Entry. If the entry has children then it's displayed
// with an ExpansionTile.
class EntryItem extends StatelessWidget {
  const EntryItem(this.entry);

  final Entry entry;

  Widget _buildTiles(Entry root) {
    if (root.children.isEmpty) return ListTile(title: Text(root.title));
    return ExpansionTile(
      key: PageStorageKey<Entry>(root),
      title: Text(root.title),
      children: root.children.map(_buildTiles).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildTiles(entry);
  }
}

void main() {
  runApp(ExpansionTileSample());
}

您可以创建自己的数据模型。

参考: https://flutter.dev/docs/catalog/samples/expansion-tile-sample

答案 1 :(得分:1)

visibleEdit 将在所有行上运行,这是一个错误,您需要在 DebitInvoiceLine 类中定义一个变量,然后使用它而不是旧的,就像这样:

       onTap: () {
                setState(() {
                  widget.dInvoiceLines[index].visibleEdit=  
                    !widget.dInvoiceLines[index].visibleEdit;
                });
              }

答案 2 :(得分:0)

您最好的办法是为每个ListTile并在其下的Row创建一个私有实例。这样,您可以对特定的小部件进行操作,而不会影响其他小部件。

免责声明:我没有使用您的代码,但是显示了实现您现在想要实现的目标的最佳方法。

主页:

class _MyHomePageState extends State<MyHomePage> {
  // This is just for demo
  List<String> _items = ['Item 1', 'Item 2', 'Item 3'];

  Widget get listTile{
    return ListView.builder(
      itemCount: _items.length,
      shrinkWrap: true,
      itemBuilder: (BuildContext context, int index){
        // This is a widget which is created out of this widget
        // and created with private instance, every instance 
        // will be having it's own bool to show/hide the Row
        // There is a widget named ListTileWidget mentioned in the code
        return ListTileWidget(title: _items[index]);
      }
    );  
  }
  
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: listTile
      )
    );
  }
}

ListTileWidget:

class _ListTileWidget extends State<ListTileWidget> {
  // This is for individual ListTile reference
  bool isSelected = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        ListTile(
          title: Text(widget.title),
          onTap: () => setState((){ isSelected = !isSelected; }) // doing toggle
        ),
        // for each listtile individually, it shows/hide Row accordingly
        isSelected 
        ? Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text("Edit"),
            SizedBox(width: 50.0),
            Text("Delete")
          ]
        ) : Container()
      ]
    );
  }
}

结果:

THIS IS HOW THE RESULT LOOK LIKE

相关问题