I use GridView to display a 2-column list of products. The right column will be pushed down a bit in order to make a staggered grid view.
To do that, I use OverflowBox for products in the right column. I get the desired UI. Each grid tile is wrapped by GestureDetector which just prints 'Tapped' when the user touches a grid tile.
However, the pushed part of the grid tile is untouchable (the red box in the image).
Here is my code snippet and screenshots for illustration:
import 'package:flutter/material.dart';
import '../models/products.dart';
import './vertical_product_card.dart';
class ProductsGrid extends StatelessWidget {
final List<Product> products;
ProductsGrid(this.products);
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(40),
bottomRight: Radius.circular(40),
),
child: Container(
color: Theme.of(context).primaryColor,
child: GridView.builder(
shrinkWrap: true,
padding:
const EdgeInsets.only(top: 10, bottom: 50, left: 15, right: 15),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: (screenWidth - 30 - 15) / (2 * 290),
mainAxisSpacing: 15,
crossAxisSpacing: 15,
// Product Card has fixed height 290, screenWidth must substract the total horizontal padding of GridView
),
itemCount: products.length,
itemBuilder: (_, i) {
if (i % 2 == 0) {
return GestureDetector(
onTap: () {
print('Tapped');
},
child: VerticalProductCard(products[i]),
);
}
return GestureDetector(
onTap: () {
print('Tapped');
},
child: OverflowBox(
maxHeight: 290.0 + 70.0,
child: Container(
margin: EdgeInsets.only(top: 70),
child: VerticalProductCard(products[i]),
),
),
);
},
),
),
);
}
}

