我想为列表视图中的每个特定项目创建一个动画

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'),
                                                              ),
                                                            ),
                                                          ),
                                                        ),
                                                      ],
                                                    )),
                                              ),
                                            ),
                                          ),
                                        ),
                                      );
                                    }),