我有一个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")
],
),
)
],
);
},
),
);
我可以通过按键进行操作还是如何获取正确的物品?
答案 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()
]
);
}
}
结果: