Guides
/
Building Search UI
/
Ecommerce ui template
/
Components
/
Product listing page display
Mar. 21, 2022
Product Card
On this page
The Product view components allow you to show your product data from an Algolia index as a product card. Use:
- The
ProductCardView
widget to display product information in a list or grid. - The
ProductItemView
widget to display product information with details in a list.
Product card
The ProductCardView
component lets you display product information. For example, you can show product cards in a list or grid view.
Code summary
You can customize ProductCardView
in:
Usage and props
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class ProductCardView extends StatelessWidget {
const ProductCardView(
{Key? key,
required this.product,
this.imageAlignment = Alignment.center,
this.onTap})
: super(key: key);
final Product product;
final Alignment imageAlignment;
final Function(String)? onTap;
@override
Widget build(BuildContext context) {
final priceValue = (product.price?.onSales ?? false)
? product.price?.discountedValue
: product.price?.value;
final crossedValue =
(product.price?.onSales ?? false) ? product.price?.value : null;
return GestureDetector(
onTap: () => onTap?.call(product.objectID!),
child: SizedBox(
width: 150,
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Stack(
alignment: AlignmentDirectional.bottomStart,
children: [
SizedBox(
height: 100,
width: MediaQuery.of(context).size.width,
child: Image.network('${product.image}',
alignment: imageAlignment, fit: BoxFit.cover)),
if (product.price?.onSales == true)
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(" ON SALE ${product.price?.discountLevel}% ",
style: Theme.of(context).textTheme.caption?.copyWith(
color: Colors.white,
backgroundColor: AppTheme.darkPink)),
)
],
),
const SizedBox(height: 8),
SizedBox(
child: Text('${product.brand}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: Theme.of(context).textTheme.caption)),
SizedBox(
child: Text('${product.name}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: Theme.of(context).textTheme.bodyText2)),
Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: ColorIndicatorView(product: product),
),
Row(
children: [
Text('$priceValue €',
maxLines: 1,
overflow: TextOverflow.clip,
softWrap: false,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontWeight: FontWeight.bold,
color: AppTheme.vividOrange)),
if (crossedValue != null)
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text('$crossedValue €',
maxLines: 1,
overflow: TextOverflow.clip,
softWrap: false,
style: Theme.of(context)
.textTheme
.caption
?.copyWith(decoration: TextDecoration.lineThrough)),
),
],
),
RatingView(
value: product.reviews?.rating?.toInt() ?? 0,
reviewsCount: product.reviews?.count?.toInt() ?? 0),
]),
),
);
}
}
Product item
The ProductItemView
component lets you display product information. For example, you can show product item with details in a list.
Code summary
You can customize ProductItemView
in:
Usage and props
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
class ProductItemView extends StatelessWidget {
const ProductItemView(
{Key? key,
required this.product,
this.imageAlignment = Alignment.center,
this.onProductPressed})
: super(key: key);
final Product product;
final Alignment imageAlignment;
final Function(String)? onProductPressed;
@override
Widget build(BuildContext context) {
final priceValue = (product.price?.onSales ?? false)
? product.price?.discountedValue
: product.price?.value;
final crossedValue =
(product.price?.onSales ?? false) ? product.price?.value : null;
return GestureDetector(
onTap: () {
onProductPressed?.call(product.objectID!);
},
child: SizedBox(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Stack(
alignment: AlignmentDirectional.bottomStart,
children: [
SizedBox(
height: 100,
width: 100,
child: Image.network('${product.image}',
alignment: imageAlignment, fit: BoxFit.cover)),
if (product.price?.onSales == true)
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
" ON SALE ${product.price?.discountLevel}% ",
style: Theme.of(context).textTheme.caption?.copyWith(
color: Colors.white,
backgroundColor: AppTheme.darkPink),
))
],
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('${product.brand}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: Theme.of(context).textTheme.caption),
Text('${product.name}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: Theme.of(context).textTheme.bodyText1),
if (product.description?.isNotEmpty == true)
Text('${product.description}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: Theme.of(context)
.textTheme
.bodyText2
?.copyWith(fontSize: 12, color: Colors.grey)),
Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: ColorIndicatorView(product: product),
),
Row(
children: [
Text('$priceValue €',
maxLines: 1,
overflow: TextOverflow.clip,
softWrap: false,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontWeight: FontWeight.bold,
color: AppTheme.vividOrange)),
if (crossedValue != null)
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text('$crossedValue €',
maxLines: 1,
overflow: TextOverflow.clip,
softWrap: false,
style: Theme.of(context)
.textTheme
.caption
?.copyWith(
decoration: TextDecoration.lineThrough)),
),
],
),
RatingView(
value: product.reviews?.rating?.toInt() ?? 0,
reviewsCount: product.reviews?.count?.toInt() ?? 0),
],
),
),
]),
),
);
}
}
Did you find this page helpful?