Building a Product Page in Flutter — Part 2

In this section, we would be completing the creating product page with Flutter tutorial. This tutorial assumes the following,
- You have a basic understanding of Flutter and know what Widgets and State management in Flutter are.
- You have a basic understanding of Dart programming language
- That you have flutter set up on your development machine.
With the above out of the way, let’s get our hands dirty. 💻
Add functionality to the colour property
We added the colour property in the previous tutorial, now we would need to make them respond to user interactions. To do that lets first extract the colour rows into a different widget called colorSelector to make the code cleaner. Your code should look like the gist below.
Now that we have separated the code, we can now create a new reusable stateless widget named ColorTicker to replace the colour containers. The widget would have a callback that listens for user taps to be sent to the main page and also handle showing the ticker when the item is selected.
Now that we have created the ColorTicker widget, we would replace the colour containers with the new widget and handle the callback. The callback would set the value of a property called selected by calling setState() which would cause the widget to rebuild its widgets.
The colorSelector widget would now look like the gist below.
Add the new property selected to the top of the _MyHomePageState
class _MyHomePageState extends State<MyHomePage> {
String selected = "blue";
And change the value of the image asset in the hero Widget to use the new property. This would make the image load the image path dynamically based on the selected image. This is possible because of the way the images were named based on their colour property.
Image.asset("images/shoe_$selected.png",),
Your hero widget should like this
Widget hero(){
return Container(
child: Stack(
children: <Widget>[
Image.asset("images/shoe_$selected.png",),
Positioned(child: appBar(),top: 0,),
Positioned(child: FloatingActionButton(
elevation: 2,
child:Image.asset("images/heart_icon_disabled.png",
width: 30,
height: 30,),
backgroundColor: Colors.white,
onPressed: (){}
),
bottom: 0,
right: 20,
),
],
),
);
}
Adding Favourite feature
We can also add the favourite feature similar way. First, add a boolean property called favourite at the top of the _MyHomePageState widget
bool favourite = false;
In the onPressed callback of the favourite Floating button, toggle the value of the newly added property and use it to select the actual image based on the value of the property.
setState(() {
favourite = !favourite;
});
Your hero widget should be looking like this now.
Widget hero(){
return Container(
child: Stack(
children: <Widget>[
Image.asset("images/shoe_$selected.png",),
Positioned(child: appBar(),top: 0,),
Positioned(child: FloatingActionButton(
elevation: 2,
child:Image.asset(favourite? "images/heart_icon.png" : "images/heart_icon_disabled.png",
width: 30,
height: 30,),
backgroundColor: Colors.white,
onPressed: (){
setState(() {
favourite = !favourite;
});
}
),
bottom: 0,
right: 20,
),
],
),
);
}
Finally, let's create the call to action button to purchase the product. We would start by creating a widget purchase made up of two widgets, the button and the price in a row.
Widget purchase(){
return Container(
padding: EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(child: Text("ADD TO BAG +",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Color(0xFF2F2F3E)
),
), color: Colors.transparent,
onPressed: (){},),
Text(r"$95",
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w100,
color: Color(0xFF2F2F3E)
),
)
],
),
);
}
We can now add the widget below the property widget in the build method
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
hero(),
description,
Property(),
purchase()
],
),
)
);
}
Uhmm, but the purchase widget is right below the property widget 🤔 but at the bottom in the design. To change that, we would need to wrap the property widget in an Expanded widget, this would cause the property to expand to fill the available space and push the purchase button to the bottom. Your build method should look like below. Run your project to see all the changes.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
hero(),
description,
Expanded (
child: Property(),
),
purchase()
],
),
)
);
}
With this, we have come to the end of the tutorial, there are still some minor modifications and refactoring that can be done.
Link to the complete code available here