Let's Build a Homemade Xylophone Flutter App

Let's Build a Homemade Xylophone Flutter App

Β·

17 min read

Hey All,

I am back with yet another app I have built while following the Angela Yu course on Udemy so I can share with you guys what I have learnt from it. So without further ado let's get started.

Alt Text

Things To Learn And Implement

These are the list of thing we are going to learn by the end of the creation of this app.

  • FlatButton widget
  • Expanded widget (Once again)
  • Importing package and Using it
  • Playing the local sound on Audio in-app
  • Different type of function call

Let's Create our Xylophone App

By the End our App is going to look something like this:

Alt Text

where each button is associated with a sound note (Can't show it you guys how it works πŸ˜” for that you have to build on your ownπŸ˜…).

Setting Up the Base Setup

So by now you already know that the base setup for our app can be done with a single flutter command.

flutter create xylophone

Now let's update the App icons for both Android and iOS by changing them In there respective folders.

Also, let's add the required note sounds after creating the asset folder and store it in this folder. Also, let's update the pubsec.yaml so that flutter recognises the added note sound files.

name: xylophone
description: A new Flutter project.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter

# The following section is specific to Flutter.
flutter:

  uses-material-design: true

  assets:
   - assets/

and run the flutter pub get to update the flutter dependencies.

You can clone this repo which contains the complete code with required assets for our app.

Let's create FlatButtons for each Sound Note

So now let's create a flat button and make it play a sound note when it's clicked.

So now let's start with our app coding

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        body: Xylophone(),
      ),
    ),
  );
}

class Xylophone extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

This provides us with a pitch Black background app without any app bar.

Now let's create a FlatButton widget which provides us with a button without any elevation. Also, the FlatButton is Now replaced By TextButton Widget

A Material Design "Text Button".

Use text buttons on toolbars, in dialogues, or inline with other content but offset from that content with padding so that the button's presence is obvious. Text buttons do not have visible borders and must therefore rely on their position relative to other content for context. In dialogues and cards, they should be grouped in one of the bottom corners. Avoid using text buttons where they would blend in with other content, for example in the middle of lists.

A text button is a labelled child displayed on a (zero elevation) Material widget. The label's Text and Icon widgets are displayed in the style's ButtonStyle.foregroundColor. The button reacts to touches by filling with the style's ButtonStyle.backgroundColor.

So Now let's 7 buttons with a different colour so we can distinguish each of them. ( I will display the code after I explain about the Importing packages)

Importing the Audioplayer package

Now as I told we need to play a tone which each of the buttons is clicked. So to make that audio play we are going to use the package which is already created by other developers so can we don't have to create our own custom code to make the audio player for our App.

To import package first we need to find the package which suits our need. So let's go to the flutter package which holds all the list of the packages which we can use in our project.

Alt Text

Once we are on the website now let's search for the audio player package which we want to play the sound when we click on the button. In result, we might get many packages with almost similar implementation out of which we have to pick the package which is best suited for the project still if you find multiple packages fulfilling your requirement then check the package pub points and popularity so that you will be using the package which has the best solution and which are frequently used by the other developersπŸ˜‰.

Once you pick your package now let's open that package and read the documentation which explains us about the package like how to install, Examples of use cases, etc.

Alt Text

By following the Installation steps mentioned in the documentation. So let's use the audioplayer package in our project. So the Updated Yaml looks like this:

name: xylophone
description: A new Flutter project.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.0
  audioplayers: 0.17.0   // This the package we have got from the flutter packages.

dev_dependencies:
  flutter_test:
    sdk: flutter

# The following section is specific to Flutter.
flutter:

  uses-material-design: true

  assets:
   - assets/

Now to Use this in our app just run the flutter pub get command so the package gets add as an external library in our project.

Now let's import the package and create an object for the player so we can use the functionalities offered by the package.

import 'package:audioplayers/audio_cache.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: Xylophone(),
      ),
    ),
  );
}

class Xylophone extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        children: [
          FlatButton(
            onPressed: () {
              final player = new AudioCache();
              player.play('note1.wav');
            },
            child: null,
            color: Colors.red,
          ),
          FlatButton(
            onPressed: () {
              final player = new AudioCache();
              player.play('note2.wav');
            },
            child: null,
            color: Colors.orange,
          ),
          FlatButton(
            onPressed: () {
              final player = new AudioCache();
              player.play('note3.wav');
            },
            child: null,
            color: Colors.yellow,
          ),
          FlatButton(
            onPressed: () {
              final player = new AudioCache();
              player.play('note4.wav');
            },
            child: null,
            color: Colors.green,
          ),
          FlatButton(
            onPressed: () {
              final player = new AudioCache();
              player.play('note5.wav');
            },
            child: null,
            color: Colors.green.shade900,
          ),
          FlatButton(
            onPressed: () {
              final player = new AudioCache();
              player.play('note6.wav');
            },
            child: null,
            color: Colors.blue,
          ),
          FlatButton(
            onPressed: () {
              final player = new AudioCache();
              player.play('note7.wav');
            },
            child: null,
            color: Colors.purple,
          ),
        ],
      ),
    );
  }
}

As you can see in the Code we have Seven FlatButton which each is set to play a tone when clicked. Also, we have used the Column widget to display the all button in a column and By using the SafeArea widget that inserts its child by sufficient padding to avoid intrusions by the operating system.

And the

    final player = new AudioCache();
    player.play('note1.wav');

Creates an object for AudioCache class which has the code for the locally stored audio files and then through the object we are accessing the method which helps us in playing the audio. (So simple right 😎 think of the time we saved from writing all those codes which we had to write make the audio player if didn't have this package.). Also we not going to change the variable player so we are making it as final which prevents the variable modification.

Also, one more thing that as you can see that we are directly mentioning the audio file name without folder name that is due to audioplayer package consider that audio files are stored inside the asset folder.

As of now, our app looks like this:

Alt Text

As you can see that buttons are not covering the whole screen which can be taken care By adding the single line inside the Column widget we can make those buttons to stretch to the end of the screen that is crossAxisAlignment: CrossAxisAlignment.stretch by adding this line the buttons are made stretch horizontally to cover the whole screen

Now as you can see that we have many repeated lines of code so we can reduce it make our code look better and cleaner by creating a function which can be used instead of repeating the same line of code again and again.

Creation of Function for the Sound Play

So let's create the function named playSound which got the code for creating the object of the AudioCache class and from that object we are accessing the play function offered by that class.

Function is a set of statements that take inputs, do some specific computation and produces output. Functions are created when certain statements are repeatedly occurring in the program and a function is created to replace them. Functions make it easy to divide the complex program into smaller sub-groups and increase the code reusability of the program.

Basically, there are four types of functions in Dart. These are as follows:

  • No arguments and no return type
  • With arguments and no return type
  • No arguments and return type
  • With arguments and with return type

So as we don't have to return anything but we need to change the sound note depending on the button so we are gonna need the With arguments and no return type type of function.

class Xylophone extends StatelessWidget {
  void playSound(int noteNumber) {
    final player = new AudioCache();
    player.play('note$noteNumber.wav');
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          FlatButton(
            onPressed: () {
              playSound(1);
            },
            child: null,
            color: Colors.red,
          ),
          FlatButton(
            onPressed: () {
              playSound(2);
            },
            child: null,
            color: Colors.orange,
          ),
          FlatButton(
            onPressed: () {
              playSound(3);
            },
            child: null,
            color: Colors.yellow,
          ),
          FlatButton(
            onPressed: () {
              playSound(4);
            },
            child: null,
            color: Colors.green,
          ),
          FlatButton(
            onPressed: () {
              playSound(5);
            },
            child: null,
            color: Colors.green.shade900,
          ),
          FlatButton(
            onPressed: () {
              playSound(6);
            },
            child: null,
            color: Colors.blue,
          ),
          FlatButton(
            onPressed: () {
              playSound(7);
            },
            child: null,
            color: Colors.purple,
          ),
        ],
      ),
    );
  }
}

Create one more Function for Button build

Still, we can see the repeated code for building the Expanded FlatButtons so let's create a function for that as well but as you can see this since we are going to call the function from inside of the Column widget it expects a widget in return from the function so the function return type should be a widget and next we also need to provide the colour of the button and number of the sound note be played for that button so we are going to use the named parameter in the function so that there will be confusion with the parameters to be passed with function.

class Xylophone extends StatelessWidget {
  void playSound(int noteNumber) {
    final player = new AudioCache();
    player.play('note$noteNumber.wav');
  }

  Expanded buildKey({Color color, int noteNumber}) {
    return Expanded(
      child: FlatButton(
        onPressed: () {
          playSound(noteNumber);
        },
        child: null,
        color: color,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          buildKey(color: Colors.red, noteNumber: 1),
          buildKey(color: Colors.orange, noteNumber: 2),
          buildKey(color: Colors.yellow, noteNumber: 3),
          buildKey(color: Colors.green, noteNumber: 4),
          buildKey(color: Colors.teal, noteNumber: 5),
          buildKey(color: Colors.blue, noteNumber: 6),
          buildKey(color: Colors.purple, noteNumber: 7),
        ],
      ),
    );
  }
}

Viola, now you see that by how many lines code we have reduced from our code using the single function.

Here is our final product which creates the sound note on clicking on the button.

Alt Text

Challenges Faced

Challenges to be faced with this project was to play the audio depending on each button and making the code clean and can be reused and finally use of the import with the dart language.

  • The Button creation issue we overcame through the use of the FlatButton widget.
  • Audio play, we imported the audioplayer package which had the functionality to play the audio and we made those function to play the audio on clicking the button
  • We removed the repeated lines of code by the use of Functions

Summary

To summarise the whole thing by creating this app we learnt the use of the import and how to use it. Using the audio player to play the audio. use of the flat button with column and stretch it across the screen and different types of the functions.

Thank you

Thank for reading the Blog till now (If you have read it till now πŸ˜…). Leave a like and comment if you liked the blog and definitely leave a comment if you found any mistakes so that I can correct myself. In next the blog, I will be back with the Quiz with the scoring system (I have just seen the preview of the app in the course and I will share with the guys what I have learnt from creating that app πŸ˜‰)

Till then 再见 πŸ‘‹