我想为列表视图中的每个特定项目创建一个动画
I want to create an animation for every specific item in list view
我有一个动态列表视图,我想在点击它时打开该项目,但是当我点击它时,所有列表项目也会打开。我只需要打开按下的项目。
我正在为动画使用动画容器,并在卡片关闭时使用 Visible 来隐藏编辑文本小部件。
**这是我的代码**
ListView.builder(
itemCount: dispoModes.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Visibility(
child: GestureDetector(
onTap: () async {
setState(() {
open = !open;
});
await Future.delayed(
Duration(
milliseconds: open
? 280
: 100), () {
setState(() {
visible = !visible;
});
});
},
child: AnimatedContainer(
decoration:
const BoxDecoration(),
width: double.infinity,
height: open ? 134 : 62,
duration: const Duration(
milliseconds: 700),
curve: Curves.fastOutSlowIn,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: open
? HexColor(
'#31679A')
: Colors
.transparent,
width: open ? 2 : 0),
borderRadius:
BorderRadius.circular(
12.0),
),
elevation: 3,
child: Container(
decoration: BoxDecoration(
color:
HexColor('#F5F6F6'),
borderRadius:
const BorderRadius
.all(
Radius.circular(
12)),
border: Border.all(
color: open
? HexColor(
'#31679A')
: HexColor(
'#F5F6F6'),
width: open ? 0 : 2),
),
margin: EdgeInsets.all(
open ? 0 : 2),
child: Align(
alignment:
Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets
.only(top: 5),
child: SizedBox(
height: 34,
child: Image.network(
"https://divadeep-admin.oxa.cloud/" +
dispoModes[index]
.imageUrl)),
),
Visibility(
visible: visible,
child: Padding(
padding:
const EdgeInsets
.fromLTRB(
25,
15,
25,
0),
child:
TextField(
keyboardType:
TextInputType
.phone,
decoration:
InputDecoration(
isDense:
true,
hintText:
'Phone Number',
hintStyle: TextStyle(
color: HexColor(
"#9B9898"),
fontSize:
17,
fontFamily:
'Segoe-UI'),
),
),
),
),
],
)),
),
),
),
),
);
}),
enter code here
将您的列表项提取为单独的 StatefulWidget
以使其具有自己的打开和可见状态
class ListItem extends StatefulWidget {
ListItem({Key? key}) : super(key: key);
@override
State<ListItem> createState() => _ListItemState();
}
class _ListItemState extends State<ListItem> {
bool open = false;
bool visible = false;
@override
Widget build(BuildContext context) {
return Visibility(
child: GestureDetector(
onTap: () async {
setState(() {
open = !open;
});
await Future.delayed(Duration(milliseconds: open ? 280 : 100), () {
setState(() {
visible = !visible;
});
});
},
child: AnimatedContainer(
decoration: const BoxDecoration(),
width: double.infinity,
height: open ? 134 : 62,
duration: const Duration(milliseconds: 700),
curve: Curves.fastOutSlowIn,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: open ? HexColor('#31679A') : Colors.transparent,
width: open ? 2 : 0),
borderRadius: BorderRadius.circular(12.0),
),
elevation: 3,
child: Container(
decoration: BoxDecoration(
color: HexColor('#F5F6F6'),
borderRadius: const BorderRadius.all(Radius.circular(12)),
border: Border.all(
color: open ? HexColor('#31679A') : HexColor('#F5F6F6'),
width: open ? 0 : 2),
),
margin: EdgeInsets.all(open ? 0 : 2),
child: Align(
alignment: Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 5),
child: SizedBox(
height: 34,
child: Image.network(
"https://divadeep-admin.oxa.cloud/" +
dispoModes[index].imageUrl)),
),
Visibility(
visible: visible,
child: Padding(
padding: const EdgeInsets.fromLTRB(25, 15, 25, 0),
child: TextField(
keyboardType: TextInputType.phone,
decoration: InputDecoration(
isDense: true,
hintText: 'Phone Number',
hintStyle: TextStyle(
color: HexColor("#9B9898"),
fontSize: 17,
fontFamily: 'Segoe-UI'),
),
),
),
),
],
)),
),
),
),
),
);
}
}
然后 return 它来自你的 ListView
作为 itemBuilder
,像这样:
ListView.builder(
itemCount: dispoModes.length,
shrinkWrap: true,
itemBuilder: (context, index) => ListItem(),
)
int selectedIndex = -1;
Widget build()
...
itemCount: dispoModes.length,
shrinkWrap: true,
itemBuilder: (context, index) {
bool open = selectedIndex == index;
return Visibility(
child: GestureDetector(
onTap: () async {
setState(() {
selectedIndex = (selectedIndex == index) ? -1 : index; // second click closes it
});
await Future.delayed(
Duration(
milliseconds: open
? 280
: 100), () {
setState(() {
// also change it here
visible = !visible;
});
});
},
child: AnimatedContainer(
decoration:
const BoxDecoration(),
width: double.infinity,
height: open ? 134 : 62,
duration: const Duration(
milliseconds: 700),
curve: Curves.fastOutSlowIn,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: open
? HexColor(
'#31679A')
: Colors
.transparent,
width: open ? 2 : 0),
borderRadius:
BorderRadius.circular(
12.0),
),
elevation: 3,
child: Container(
decoration: BoxDecoration(
color:
HexColor('#F5F6F6'),
borderRadius:
const BorderRadius
.all(
Radius.circular(
12)),
border: Border.all(
color: open
? HexColor(
'#31679A')
: HexColor(
'#F5F6F6'),
width: open ? 0 : 2),
),
margin: EdgeInsets.all(
open ? 0 : 2),
child: Align(
alignment:
Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets
.only(top: 5),
child: SizedBox(
height: 34,
child: Image.network(
"https://divadeep-admin.oxa.cloud/" +
dispoModes[index]
.imageUrl)),
),
Visibility(
visible: visible,
child: Padding(
padding:
const EdgeInsets
.fromLTRB(
25,
15,
25,
0),
child:
TextField(
keyboardType:
TextInputType
.phone,
decoration:
InputDecoration(
isDense:
true,
hintText:
'Phone Number',
hintStyle: TextStyle(
color: HexColor(
"#9B9898"),
fontSize:
17,
fontFamily:
'Segoe-UI'),
),
),
),
),
],
)),
),
),
),
),
);
}),
我有一个动态列表视图,我想在点击它时打开该项目,但是当我点击它时,所有列表项目也会打开。我只需要打开按下的项目。 我正在为动画使用动画容器,并在卡片关闭时使用 Visible 来隐藏编辑文本小部件。
**这是我的代码**
ListView.builder(
itemCount: dispoModes.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Visibility(
child: GestureDetector(
onTap: () async {
setState(() {
open = !open;
});
await Future.delayed(
Duration(
milliseconds: open
? 280
: 100), () {
setState(() {
visible = !visible;
});
});
},
child: AnimatedContainer(
decoration:
const BoxDecoration(),
width: double.infinity,
height: open ? 134 : 62,
duration: const Duration(
milliseconds: 700),
curve: Curves.fastOutSlowIn,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: open
? HexColor(
'#31679A')
: Colors
.transparent,
width: open ? 2 : 0),
borderRadius:
BorderRadius.circular(
12.0),
),
elevation: 3,
child: Container(
decoration: BoxDecoration(
color:
HexColor('#F5F6F6'),
borderRadius:
const BorderRadius
.all(
Radius.circular(
12)),
border: Border.all(
color: open
? HexColor(
'#31679A')
: HexColor(
'#F5F6F6'),
width: open ? 0 : 2),
),
margin: EdgeInsets.all(
open ? 0 : 2),
child: Align(
alignment:
Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets
.only(top: 5),
child: SizedBox(
height: 34,
child: Image.network(
"https://divadeep-admin.oxa.cloud/" +
dispoModes[index]
.imageUrl)),
),
Visibility(
visible: visible,
child: Padding(
padding:
const EdgeInsets
.fromLTRB(
25,
15,
25,
0),
child:
TextField(
keyboardType:
TextInputType
.phone,
decoration:
InputDecoration(
isDense:
true,
hintText:
'Phone Number',
hintStyle: TextStyle(
color: HexColor(
"#9B9898"),
fontSize:
17,
fontFamily:
'Segoe-UI'),
),
),
),
),
],
)),
),
),
),
),
);
}),
enter code here
将您的列表项提取为单独的 StatefulWidget
以使其具有自己的打开和可见状态
class ListItem extends StatefulWidget {
ListItem({Key? key}) : super(key: key);
@override
State<ListItem> createState() => _ListItemState();
}
class _ListItemState extends State<ListItem> {
bool open = false;
bool visible = false;
@override
Widget build(BuildContext context) {
return Visibility(
child: GestureDetector(
onTap: () async {
setState(() {
open = !open;
});
await Future.delayed(Duration(milliseconds: open ? 280 : 100), () {
setState(() {
visible = !visible;
});
});
},
child: AnimatedContainer(
decoration: const BoxDecoration(),
width: double.infinity,
height: open ? 134 : 62,
duration: const Duration(milliseconds: 700),
curve: Curves.fastOutSlowIn,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: open ? HexColor('#31679A') : Colors.transparent,
width: open ? 2 : 0),
borderRadius: BorderRadius.circular(12.0),
),
elevation: 3,
child: Container(
decoration: BoxDecoration(
color: HexColor('#F5F6F6'),
borderRadius: const BorderRadius.all(Radius.circular(12)),
border: Border.all(
color: open ? HexColor('#31679A') : HexColor('#F5F6F6'),
width: open ? 0 : 2),
),
margin: EdgeInsets.all(open ? 0 : 2),
child: Align(
alignment: Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 5),
child: SizedBox(
height: 34,
child: Image.network(
"https://divadeep-admin.oxa.cloud/" +
dispoModes[index].imageUrl)),
),
Visibility(
visible: visible,
child: Padding(
padding: const EdgeInsets.fromLTRB(25, 15, 25, 0),
child: TextField(
keyboardType: TextInputType.phone,
decoration: InputDecoration(
isDense: true,
hintText: 'Phone Number',
hintStyle: TextStyle(
color: HexColor("#9B9898"),
fontSize: 17,
fontFamily: 'Segoe-UI'),
),
),
),
),
],
)),
),
),
),
),
);
}
}
然后 return 它来自你的 ListView
作为 itemBuilder
,像这样:
ListView.builder(
itemCount: dispoModes.length,
shrinkWrap: true,
itemBuilder: (context, index) => ListItem(),
)
int selectedIndex = -1;
Widget build()
...
itemCount: dispoModes.length,
shrinkWrap: true,
itemBuilder: (context, index) {
bool open = selectedIndex == index;
return Visibility(
child: GestureDetector(
onTap: () async {
setState(() {
selectedIndex = (selectedIndex == index) ? -1 : index; // second click closes it
});
await Future.delayed(
Duration(
milliseconds: open
? 280
: 100), () {
setState(() {
// also change it here
visible = !visible;
});
});
},
child: AnimatedContainer(
decoration:
const BoxDecoration(),
width: double.infinity,
height: open ? 134 : 62,
duration: const Duration(
milliseconds: 700),
curve: Curves.fastOutSlowIn,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: open
? HexColor(
'#31679A')
: Colors
.transparent,
width: open ? 2 : 0),
borderRadius:
BorderRadius.circular(
12.0),
),
elevation: 3,
child: Container(
decoration: BoxDecoration(
color:
HexColor('#F5F6F6'),
borderRadius:
const BorderRadius
.all(
Radius.circular(
12)),
border: Border.all(
color: open
? HexColor(
'#31679A')
: HexColor(
'#F5F6F6'),
width: open ? 0 : 2),
),
margin: EdgeInsets.all(
open ? 0 : 2),
child: Align(
alignment:
Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets
.only(top: 5),
child: SizedBox(
height: 34,
child: Image.network(
"https://divadeep-admin.oxa.cloud/" +
dispoModes[index]
.imageUrl)),
),
Visibility(
visible: visible,
child: Padding(
padding:
const EdgeInsets
.fromLTRB(
25,
15,
25,
0),
child:
TextField(
keyboardType:
TextInputType
.phone,
decoration:
InputDecoration(
isDense:
true,
hintText:
'Phone Number',
hintStyle: TextStyle(
color: HexColor(
"#9B9898"),
fontSize:
17,
fontFamily:
'Segoe-UI'),
),
),
),
),
],
)),
),
),
),
),
);
}),