The course detail page consists of three sections: a banner at the top with the course image, a main section with the course title and description, and then a section with some course details.
In the details, you’ll list the course difficulty value. The data coming back from the API is lowercase, so you’ll take this opportunity to write an extension on the String class with a method to capitalize a string, since that’s missing from the String class itself.
Open your project in progress or download and open the starter project. In the lib folder, create a folder called utils. Next, create a file called string_extensions.dart. Add an extension on the String class called StringExtension
extension StringExtension on String {
}
Add a capitalize method to the extension, which makes the first letter uppercase, then extracts the rest of the string using substring.
String capitalize() {
return '${this[0].toUpperCase()}${substring(1)}';
}
Now open course_details_page.dart. You can find this in the ui and courses folders. We’re going to use the ImageContainer we built previously. Before we can use it, we first must import some files.
import '../course_detail/image_container.dart';
import '../../utils/string_extensions.dart';
Now we’re going to build several methods to build out the course details page. First, let’s build our banner that contains our Image Container.
Widget _buildBanner() {
return ImageContainer(
height: 200,
url: course.artworkUrl,
);
}
By not specifying a width on the ImageContainer, it will take up the full width of the screen. Now add _buildMain helper method to show the course title and description in Text widgets
Widget _buildMain(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
course.name,
style:
Theme.of(context).textTheme.subtitle2?.copyWith(fontSize: 24),
),
Text(
course.description,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w300),
),
],
),
);
}
Finally, add a _buildDetails method to show the course domains, difficulty, and contributors.
Widget _buildDetails(BuildContext context) {
const style = TextStyle(fontSize: 16);
return Padding(
padding: const EdgeInsets.only(left: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Domain(s): ${course.domainsString}',
style: style,
),
Text(
'Level: ${course.difficulty.capitalize()}',
style: style,
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'${course.contributors}',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
],
),
);
}
The difficulty level was capitalized using the String extension. Okay, now to put it all to work. Update the build method to call the helpers.
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildBanner(),
_buildMain(context),
_buildDetails(context),
],
),
And that’s it. Build and run or hot reload your app. Tap on one of the courses, and this time, you have a nicely formatted course page.