简体   繁体   中英

Flutter: How to expand/collapse (show/hide) a Row in a GridView or Wrap widget

I'm trying to build a GridView where selected the item can expand/collapse (show/hide) a row in the immediate consecutive row of the selected item, like an information box.

On the screenshot below I'm showing an example where the Node 001 is selected.

Don't know if I can achieve this with GridView widget or Wrap Widget, but any help will be very appreciated.

Thanks in advance for your support.

Sample mockup screenshot: 样机截图示例

My actual GridView code:

GridView.builder(
              shrinkWrap: true,
              padding: EdgeInsets.zero,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 4,
                  crossAxisSpacing: 5,
                  mainAxisSpacing: 5,
                  mainAxisExtent: 40),
              itemCount: nodes.length,
              itemBuilder: (BuildContext context, int index) {
                return TextButton(
                  onPressed: (selectedNode == nodes[index].slaveId)
                      ? () {}
                      : () =>
                          Provider.of<SelectedNode>(context, listen: false)
                              .value = nodes[index].slaveId!,
                  style: TextButton.styleFrom(
                      backgroundColor:
                          (selectedNode == nodes[index].slaveId)
                              ? selectedColor
                              : unselectedColor),
                  child: Text(
                      'Node ${nodes[index].slaveId.toString().padLeft(3, '0')}'),
                );
              },
            )

Modified code:

SizedBox(
        width: double.infinity,
        child: SizedBox(
          height: MediaQuery.of(context).size.height / 3.2,
          child: GridView.builder(
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 4,
                  crossAxisSpacing: 5,
                  mainAxisSpacing: 5,
                  mainAxisExtent: 40),
              itemCount: [1, 2, 3, 4, 5, 6, 7, 8, 9].length + 1,
              clipBehavior: Clip.none,
              itemBuilder: (context, index) {
                if (index != 1) {
                  return Stack(
                    clipBehavior: Clip.none,
                    children: [
                      TextButton(
                        onPressed: (selectedNode == nodes[index].slaveId)
                            ? () {}
                            : () => Provider.of<SelectedNode>(context,
                                    listen: false)
                                .value = nodes[index].slaveId!,
                        style: TextButton.styleFrom(
                            backgroundColor:
                                (selectedNode == nodes[index].slaveId)
                                    ? selectedColor
                                    : unselectedColor),
                        child: Text(
                            'Node ${nodes[index].slaveId.toString().padLeft(3, '0')}'),
                      ),
                      index == 0
                          ? Positioned(
                              child: Text('1hjkkhj'),
                              bottom: -20,
                              left: 0,
                              right: 0,
                            )
                          : SizedBox(),
                    ],
                  );
                } else {
                  return TextButton(
                    onPressed: (selectedNode == nodes[index].slaveId)
                        ? () {}
                        : () => Provider.of<SelectedNode>(context,
                                listen: false)
                            .value = nodes[index].slaveId!,
                    style: TextButton.styleFrom(
                        backgroundColor:
                            (selectedNode == nodes[index].slaveId)
                                ? selectedColor
                                : unselectedColor),
                    child: Text(
                        'Node ${nodes[index].slaveId.toString().padLeft(3, '0')}'),
                  );
                }
              }),
        ),
      ),

you can get the selected index and dived it to 4 and round up the result should give you the row number which that item click, so call this selectedRow row. in your grid view you can use selectedRow and add empty space for the next row. After that change item widget that you show in grid view and add it in a stack and add another container that contain your expanded widget. also remember that you should set stack and grid view clipBehavior to Clip.none .

something like this:

ListView.builder(
            padding: const EdgeInsets.all(8),
            itemCount: [1, 2, 3].length + 1,
            clipBehavior: Clip.none,
            itemBuilder: (context, index) {
              if (index != 2) {
                return Stack(
                  clipBehavior: Clip.none,
                  children: [
                    Text('dasdasdasd'),
                    index == 1
                        ? Positioned(
                            child: Text('1hjkkhj'),
                            bottom: -20,
                            left: 0,
                            right: 0,
                          )
                        : SizedBox(),
                  ],
                );
              } else {
                return SizedBox(
                  height: 20,
                );
              }
            })

I know it is listview but the concept work in gridview too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM