Notes: 04. Setup the Audio Widget
const keyword is used to create a constant value, be it a variable or a widget. The Text value is going to remain the same throughout the widget’s lifecycle. Hence we add a const keyword so that the widget is not rebuilt every time. This helps in improving performance. SizedBox widget is used to add space between widgets. The value won’t be changed in the widget’s lifecycle so we add a const keyword.
The students materials have been reviewed and are updated as of September 2022. The update material uses null safety and also proper use of const and final keywords as per the latest Flutter guidelines. This is to encourage the students to use the latest Flutter best practices.
In previous episodes, we learnt how to create a custom reusable widget. Now, there are different types of custom reusable widgets. The episode card we just created was reused where we wanted a different UI layout but the UI still displayed the same data. This is design centric and mainly for reusing designs. These type of reusable widgets are common in UI libraries where we reuse and customize the design for the provided widgets.
We also have other custom reusable widgets that is not UI dependent. Like where the widget can be reused but its core is not dependent on UIs or sometimes doesnt even display a UI. These could be functionality specific. This can be seen in libraries like a dependency injection library that provides custom widgets that have functionalities that can be reused in different parts of our app or in different projects.
You’re definately not limited to the types mentioned here as different scenarios would bring about more types of reusable widgets.
Now, the second reusable widget would not really be like the first one. We’ll be creating an Audio Widget which acts as skin that a developer can use with any audio player plugin. This widget has a bit of both types since we would be reusing its design and some basic functionality it has.
The UI is simple. This is how it would always look but this widget can be reused in different parts of our app or shared as a library for other projects. Let’s break down this design and see how we could start coding it. (fade in the breakdown).
We should be able to pull this off with an IconButton, some text widgets, a slide and a container. And if you’re observant, you should see that all these widgets would be placed inside a Row. Let’s go ahead and start building it.
Demo
Inside Android Studio, create a new file inside the widgets folder and name it audio_widget.dart.
First create a stateless widget named AudioWidget.
Then enter the following code:
class AudioWidget extends StatelessWidget {
const AudioWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: Row(
children: [
IconButton(icon: const Icon(Icons.play_arrow), onPressed: () {}),
// Const keyword is used to create a constant value, be it a variable or a widget.
// The Text value is going to remain the same throughout the widget's lifecycle.
// Hence we add a const keyword so that the widget is not rebuilt every time.
// This helps in improving performance.
const Text('00:37'),
Slider(value: 0, onChanged: (double value) {}),
const Text('01:15'),
],
),
);
}
}
All the widgets are laid out in a Row widget.
Now head over to the episode_screen,dart file.
Scroll to the bottom of the file and inside the AudioPlayer widget, replace the container with the AudioWiget.
And make sure you do the import.
Save your work.
And you should now have the basic audio widget displayed.
Okay, let’s do some customizations.
First, i’ll give the container a grey color like so: color: Colors.grey[300],. (save)
and then i’ll add some height to the widget: height: 60.
Next, let’s work on slider.
Add the following code:
Slider(
value: 0.5,
activeColor: Theme.of(context).textTheme.bodyText2.color,
inactiveColor: Theme.of(context).disabledColor,
onChanged: (value){},
),
The range of a slider is from 0.0 to 1.0. We set the value of the slider to 0.5 which sets it to the mid-point. Next, we set the active and inactive colors of the slider to colors gotten from the theme. The advantage of using theme colors is that the colors would be updated to match the theme for both dartk and light modes.
I can also notice that we have some empty space at the right side of the widget.
We could wrap the slider with an expanded widget so it could flex to take up any remaining space.
Click on the slider and press Alt + Enter or Option + Return if you’re on a Mac. This opens up hte Flutter fix menu.
Select “Wrap with Widget” and then change it to an Expanded widget.
Uhhmm…it looks like we need some padding on the right.
Go ahead and add a sizedbox as the last child of the row like so:
...
// SizedBox widget is used to add space between widgets. The value wont
// be changesd in the widget's lifecycle so we add a const keyword.
const SizedBox(width: 16),
Cool, everything looks good now.
Now that we’re done with the design. Let’s determine the user interaction. There are four main activities for the audio widget. (fade them in) Not android activities but things that can affect or be affected as the audio plays.
We have the play/pause button which plays or pauses the audio when the user clicks the button. And while the audio is playing, a pause icon would be displayed. Also, when we get to the end of the track, it would revert to the play button.
Next, we have the current time label. The app’s user doesnt interact with this label but the developer needs a way to update it based on whatever audio plugin they are using.
We also have the seek bar that displays the current position of the track based on the elapsed time. The user can interact with it by sliding it to a new position which resumes the track from the new position. Finally, we have the total time. For this, the developer needs to be able to set it based on the length of the audio file.