Flutter GridView Expandedable Tile

486 Views Asked by At

enter image description here

Hi, Everyone;

I need help on Fluter GridView

I want to build a simple gallery view but i haven't reached my goal yet

I have a urlImage List on simple image gridView. When select one of those image the selected image will expanded with some info Thats what I want to do.

i need help with this

Thank you.

flutter_staggered_grid_view

class _HomeScreenState extends State<HomeScreen> {
      @override
      Widget build(BuildContext context) {
        return testWidget();
      }

  bool expanded = false;

  var nodeSize = [
    NodeSize(2, 3),
    NodeSize(2, 3),
    NodeSize(2, 2),
    NodeSize(2, 2),
    NodeSize(2, 2),
    NodeSize(2, 2),
    NodeSize(2, 2),
    NodeSize(2, 3),
    NodeSize(2, 3),
    NodeSize(2, 3),
    NodeSize(2, 3),
  ];

  List<String> listImages = [
    "https://images.unsplash.com/photo-1572537165377-627a37043464?ixid=MnwxMjA3fDB8MHxzZWFyY2h8NXx8cGl4ZWx8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1572204292164-b35ba943fca7?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Nnx8cGl4ZWx8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1590254553792-7e91903c5357?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fHBpeGVsfGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1548586196-aa5803b77379?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTd8fHBpeGVsfGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1572447454458-e68d82f828b3?ixid=MnwxMjA3fDB8MHxzZWFyY2h8ODd8fHBpeGVsfGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1572204304559-b5f5380482c5?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTA4fHxwaXhlbHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1554516829-a3fce6ddbc6e?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTQzfHxwaXhlbHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1563642421748-5047b6585a4a?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTY2fHxwaXhlbHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
    "https://images.unsplash.com/photo-1593439147804-c6c7656530ae?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MzUzfHxwaXhlbHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
  ];

  Widget testWidget() {
    var tiles = [
      for (int i = 0; i < 9; i++) GridTile(nodeSize[i].x, nodeSize[i].y),
    ];

    return Expanded(
      child: SingleChildScrollView(
        child: StaggeredGrid.count(
          crossAxisCount: 4,
          mainAxisSpacing: 8,
          crossAxisSpacing: 8,
          children: [
            ...tiles.mapIndexed((index, tile) {
              return StaggeredGridTile.count(
                crossAxisCellCount: tile.crossAxisCount.toInt(),
                mainAxisCellCount: tile.mainAxisCount,
                child: GestureDetector(
                  onTap: () async {
                    setState(() {
                      if (expanded) {
                        nodeSize[index].x = 4;
                        nodeSize[index].y = 4.2;
                        expanded = false;
                      } else {
                        nodeSize[index].x = 2;
                        nodeSize[index].y = 2;
                        expanded = true;
                      }
                    });
                  },
                  child: nodeSize[index].x == 2
                      ? ClipRRect(
                          borderRadius: BorderRadius.all(Radius.circular(12)),
                          child: FadeInImage.memoryNetwork(
                              placeholder: kTransparentImage,
                              image: listImages[index],
                              fit: BoxFit.cover),
                        )
                      : PostRow(listImages[index]),
                ),
              );
            }),
          ],
        ),
      ),
    );
  }
}

class NodeSize {
  NodeSize(this.x, this.y);
  double x;
  double y;
}

class GridTile {
  const GridTile(this.crossAxisCount, this.mainAxisCount);
  final double crossAxisCount;
  final double mainAxisCount;
}

class PostRow extends StatefulWidget {
  String imageURL;
  PostRow(this.imageURL);

  @override
  State<PostRow> createState() => _PostRowState();
}

class _PostRowState extends State<PostRow> {
  ApiManager apiManager = new ApiManager();

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(left: 3.0.w, right: 3.0.w, bottom: 3.w),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(10),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(
            height: 2.h,
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              SizedBox(
                width: 40.w,
                child: FittedBox(
                  alignment: Alignment.centerLeft,
                  fit: BoxFit.scaleDown,
                  child: Text("UserName",
                      style: TextStyle(
                          fontSize: 13.sp,
                          color: Color(0xff272727),
                          fontWeight: FontWeight.w500)),
                ),
              ),
              Spacer(),
            ],
          ),
          SizedBox(height: 1.h),
          ClipRRect(
            borderRadius: BorderRadius.circular(10.0),
            child: FadeInImage.assetNetwork(
              placeholder: 'assets/images/placeholder.png',
              imageErrorBuilder: (context, error, stackTrace) {
                print('Error is $error , stack is $stackTrace');
                return Image.asset(
                  'assets/images/placeholder.png',
                );
              },
              image: widget.imageURL,
              fit: BoxFit.fill,
              fadeInDuration: const Duration(seconds: 1),
              fadeOutDuration: const Duration(milliseconds: 1),
            ),
          ),
          SizedBox(height: 1.h),
          Padding(
            padding: EdgeInsets.only(left: 3.w),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text("Text Title here....."),
                Row(
                  children: [
                    SvgPicture.asset(
                      "assets/svg/openeyeicon.svg",
                    ),
                    SizedBox(width: 2.w),
                    Text("430", style: TextStyle(fontWeight: FontWeight.w500)),
                  ],
                ),
                SizedBox(width: 2.w),
                Text(
                  "172",
                  style: TextStyle(fontWeight: FontWeight.w500),
                ),
              ],
            ),
          ),
          SizedBox(height: 2.h),
          Padding(
            padding: EdgeInsets.only(left: 3.w),
            child: Text(
              "1 hour ago",
              style: TextStyle(color: Colors.grey, fontSize: 9.sp),
            ),
          ),
        ],
      ),
    );
  }
}

This what I have right now;

1

There are 1 best solutions below

0
On BEST ANSWER

First, Make a model with nullable

class ImageItem{
  String? imageName;
  String? imageDesc;
  String? imagePrice;
  String? imageUrl;
  ServiceItem(
    this.imageName, 
    this.imageDesc, 
    this.imagePrice, 
    this.imageUrl
  );
}

make a bool var to check click

bool isClick = false;

Make a List

static List<ImageItem> myList = [
    ImageItem("Android", "Get amarseba Android app within big discount", "200", "https://images.unsplash.com/photo-1593439147804-c6c7656530ae?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MzUzfHxwaXhlbHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60"),
    ImageItem("Apple", "Hurry! Amarseba IOS app already launched! Take your ones", "300", "https://images.unsplash.com/photo-1563642421748-5047b6585a4a?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTY2fHxwaXhlbHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60"),
  ];

Now it's time to view

GridView.count(
  childAspectRatio: 1,
  crossAxisCount: 2,
  crossAxisSpacing: 8,
  mainAxisSpacing: 8,
  children: myList.map((data) {

  return InkWell(
    onTap: (){
      setState(() {
         isClick = true;   
      });
    },
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        isClick ? Text(data.imageDesc!,) : null,
        Image.asset(data.ImageUrl!, width: !isClick ? 100 : double.infinity,), //I'll not use Expanded
        heightSizedBox,
        isClick ? Text(data.imageName!,) : null, //if null unexpected use dummy SizedBox or Container.
      ],
    ),
  );

}).toList(),
)