Flutter 在点击的索引处更新数据 onClick
Posted
技术标签:
【中文标题】Flutter 在点击的索引处更新数据 onClick【英文标题】:Flutter update data onClick at clicked index 【发布时间】:2020-04-14 10:52:20 【问题描述】:我正在构建一个食品车应用程序,并在菜单项页面上有一个查询。
我的菜单项页面包含一个列表视图,其中显示每个项目的描述以及指定项目数量的选项(1、2、3....)
现在我可以增加或减少单个项目的项目计数,但不确定如何在用户单击的特定索引处的列表视图中执行此操作。
有人可以帮我解决这个问题吗?
到目前为止我所做的代码如下:
FutureBuilder(
future: getItemList(),
builder: (context, snapshot)
if (!snapshot.hasData)
return CircularProgressIndicator();
var itemList = snapshot.data;
int itemlength = itemList.length;
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index)
return Container(
height: 100,
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
decoration: BoxDecoration(
color: Colors.white70,
border: Border.all(width: 2.0, color: Colors.blueGrey),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0),
],
),
child: Row(
children: < Widget > [
Container(
width: 75,
child: ClipRRect(
borderRadius: new BorderRadius.circular(10.0),
child: Image(
image: AssetImage(
'assets/images/loginbg3.jpg'),
fit: BoxFit.cover,
),
),
margin: EdgeInsets.only(left: 10),
),
Expanded(
child: Container(
child: Column(
children: < Widget > [
Row(
children: < Widget > [
Expanded(child: Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text(itemList[index]['itemname'], style: kClickableTextStyle, ))),
Container(color: Colors.white, width: 25, margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Image.asset(_itemtype)),
],
),
Row(
children: < Widget > [
Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text('Price : ', style: kListTitleTextStyle, )),
Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text(numberofitems.toString() + ' \u20B9 ', style: kListTitleTextStyle, )),
],
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: 10),
child: Row(
children: < Widget > [
InkWell(
onTap: onClickDelete,
child: Container(
width: 30, child: Icon(
Icons.remove_circle_outline,
color: Colors.green,
size: 30,
), ),
),
Container(
width: 30,
child: Center(child: Text(_count.toString(), style: TextStyle(fontSize: 25), )),
),
InkWell(
onTap: onClickAdd,
child: Container(
margin: EdgeInsets.only(right: 5),
width: 30, child: Icon(
Icons.add_circle_outline,
color: Colors.green,
size: 30,
), ),
),
],
),
),
],
),
);
,
itemCount: itemList == null ? 0 : itemList.length,
);
)
【问题讨论】:
【参考方案1】:您可以在下面复制粘贴运行完整代码 第 1 步:创建 Item 类 第 2 步:更改未来的构建器调用 第 3 步:处理 Inkwell onTap
工作演示
代码sn-p
Future callback;
@override
void initState()
callback = _getItemList();
super.initState();
@override
Widget build(BuildContext context)
var futureBuilder = FutureBuilder(
future: callback,
...
InkWell(
onTap: ()
if (itemList[index].numberofitems > 0)
setState(()
itemList[index].numberofitems =
itemList[index].numberofitems - 1;
);
,
...
InkWell(
onTap: ()
setState(()
itemList[index].numberofitems =
itemList[index].numberofitems + 1;
print(
' $itemList[index].itemname.toString() $itemList[index].numberofitems.toString()');
);
,
完整代码
import 'dart:async';
import 'dart:collection';
import 'package:flutter/material.dart';
void main() => runApp( MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
class Item
String itemname;
String itemtype;
int numberofitems;
Item(this.itemname, this.itemtype, this.numberofitems);
class MyHomePage extends StatefulWidget
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
Future callback;
@override
void initState()
callback = _getItemList();
super.initState();
@override
Widget build(BuildContext context)
var futureBuilder = FutureBuilder(
future: callback,
builder: (BuildContext context, AsyncSnapshot snapshot)
switch (snapshot.connectionState)
case ConnectionState.none:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError)
return Text('Error: $snapshot.error');
else
return createListView(context, snapshot);
,
);
return Scaffold(
appBar: AppBar(
title: Text("Home Page"),
),
body: futureBuilder,
);
Future<List<Item>> _getItemList() async
var values = List<Item>();
values.add(
Item(itemname: "A", itemtype: "assets/images/a.jpg", numberofitems: 0));
values.add(
Item(itemname: "B", itemtype: "assets/images/a.jpg", numberofitems: 1));
values.add(
Item(itemname: "C", itemtype: "assets/images/a.jpg", numberofitems: 2));
//throw Exception("Danger Will Robinson!!!");
await Future.delayed( Duration(seconds: 2));
return values;
Widget createListView(BuildContext context, AsyncSnapshot snapshot)
List<Item> itemList = snapshot.data;
return ListView.builder(
itemCount: itemList.length,
itemBuilder: (BuildContext context, int index)
return Container(
height: 100,
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
decoration: BoxDecoration(
color: Colors.white70,
border: Border.all(width: 2.0, color: Colors.blueGrey),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0),
],
),
child: Row(
children: <Widget>[
Container(
width: 75,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image(
image: AssetImage('assets/images/a.jpg'),
fit: BoxFit.cover,
),
),
margin: EdgeInsets.only(left: 10),
),
Expanded(
child: Container(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
itemList[index].itemname,
))),
Container(
color: Colors.white,
width: 25,
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Image.asset(itemList[index].itemtype)),
],
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
'Price : ',
)),
Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
itemList[index].numberofitems.toString() +
' \u20B9 ',
)),
],
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: 10),
child: Row(
children: <Widget>[
InkWell(
onTap: ()
if (itemList[index].numberofitems > 0)
setState(()
itemList[index].numberofitems =
itemList[index].numberofitems - 1;
);
,
child: Container(
width: 30,
child: Icon(
Icons.remove_circle_outline,
color: Colors.green,
size: 30,
),
),
),
Container(
width: 30,
child: Center(
child: Text(
itemList[index].numberofitems.toString(),
style: TextStyle(fontSize: 25),
)),
),
InkWell(
onTap: ()
setState(()
itemList[index].numberofitems =
itemList[index].numberofitems + 1;
print(
' $itemList[index].itemname.toString() $itemList[index].numberofitems.toString()');
);
,
child: Container(
margin: EdgeInsets.only(right: 5),
width: 30,
child: Icon(
Icons.add_circle_outline,
color: Colors.green,
size: 30,
),
),
),
],
),
),
],
),
);
;
);
【讨论】:
你成就了我的一天。谢谢:)【参考方案2】:您需要为您的项目创建对象列表。
class Item
String name;
String description;
int quantity;
double price;
在点击项目时,使用新的递增/递减值获取单击项目的索引,并更新 setState() 中的对象列表。
【讨论】:
【参考方案3】:您需要用GestureDetector 包装您的itemBuilder 项目,即容器,然后在该检测器中调用onTap()
方法。
在此之前,您必须将您的项目转换为带有变量的有状态小部件以保持数量计数。
【讨论】:
以上是关于Flutter 在点击的索引处更新数据 onClick的主要内容,如果未能解决你的问题,请参考以下文章
Vue.js 源码分析(二十) 指令篇 v-once指令详解
如何在 Dart (Flutter) 中获取每个可迭代值的索引号