5.3 Mehrere Sounds abspielen und Funktionen
An dieser Stelle besitzen wir eine App, die nur über eine einzige Schaltfläche verfügt und einen einzigen Sound abspielen kann. Unsere Xylofon-App sollte am Schluss aber 7 Tasten besitzen und 7 verschiedene Sounds abspielen.
Übung
Versuchen Sie die restlichen 6 Tasten und Audiodateien in Ihre App zu integrieren. Probieren Sie ebenfalls mit einem Farbschema zu arbeiten, um die Tasten/Sounds voneinander auseinanderhalten zu können. Machen Sie sich bei der Übung nicht zu viele Gedanken über das Layout, wir werden dieses später noch korrigieren. Achten Sie in Ihrem Lösungsansatz mal nur auf die Funktionalität. Alle TextButton-Widgets sollten als Kinder in einem Column-Widget auftauchen. Damit bei der Beschreibung des TextButtons nicht sieben mal der Text Hier klicken erscheint, kann der Text durch einen leeren String '' ersetzt werden. Über style: TextButton.styleFrom(backgroundColor: Colors.red), wird die Schaltfläche rot eingefärbt. Verwenden Sie als Ausgangspunkt das folgende Codefragment.
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Column(
children: [
// alle Tasten sollten hier als child-Widgets erscheinen
TextButton(
onPressed: () {
final AudioPlayer player = AudioPlayer();
player.setAsset('assets/note1.wav');
player.play();
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.red),
)
],
),
),
),
);
}
}
Funktionen erstellen
Die Xylofon-App verfügt jetzt über die gewünschte Funktionalität, aber Sie können sehen, dass unser Code nicht sehr hübsch ist, da sich darin viel repetitiver Code befindet. Wie können wir die sich wiederholenden Teile reduzieren, damit beim Programmieren weniger Dinge schief gehen und wir weniger Stellen besitzen, an denen wir nach Fehler suchen müssen?
Die Antwort lautet eine Funktion verwenden. Funktionen sind von Vorteil, da sie Wiederholungen verhindern. Zudem wirkt der Programmcode durch Anwendung von Funktionen klar strukturiert und ist einfacher zu lesen.
Theorie
[Dart] Funktionen
Grundsätzlich versuchen wir mit Funktionen, Programmcode in einen Block zu packen und diesen Code-Block wiederholt aufzurufen. Dies schützt uns davor, immer wieder den gleichen Code einzutippen. Wie Sie bereits wissen, ist die Programmiersprache Dart die Grundlage von Flutter. Daher ist das Erstellen von Funktionen in Flutter dasselbe wie das Erstellen von Funktionen in Dart. Sie können eine einfache Funktion in Flutter wie folgt erstellen.
void printText (String text) {
print(text);
}
Wie Sie sehen, entspricht das Schlagwort void dem, was Sie in der Funktion zurückgeben (void würde bedeuten, dass die Funktion nichts zurückgibt). printText ist der Name der Funktion und der String text ist der Parameter, der an die Funktion übergeben wird. Sie können void auch weglassen und die Funktion folgendermassen schreiben.
printText (String text) {
print(text);
}
Wenn die Funktion etwas zurückgeben soll, müssen Sie den Datentyp vor dem Funktionsnamen angeben.
String printText (String text) {
return text;
}
In Ihrem Widget können Sie die Funktion anschliessend wie folgt aufrufen.
printText('Bäumlihof rocks')
Im Folgenden das vollständige Beispiel, in dem die obige Funktion verwendet wird, um den Text Bäumlihof rocks darzustellen.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
String printText (String text) {
print(text);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Text(printText('Bäumlihof rocks')),
),
),
);
}
}
Als erstes möchten wir den Code für die Erzeugung der player-Instanzen und Auswahl der Audiodateien in eine Funktion mit dem Namen playSound ausgliedern. Die Funktion playSound nimmt als Parameter eine Zahl vom Datentyp int. Dieser int Parameter wird innerhalb der Funktion an die play Methode der player-Instanz übergeben. Das $-Zeichen dient hier lediglich als Platzhalter für die Nummer der Audiodatei. In den child-Widgets wird die playSound Funktion anschliessend mit der Nummer der entsprechenden Audiodatei aufgerufen.
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
void playSound(int audioSample) {
final AudioPlayer player = AudioPlayer();
player.setAsset('assets/note$audioSample.wav');
player.play();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Column(
children: [
TextButton(
onPressed: () {
playSound(1);
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.red),
),
TextButton(
onPressed: () {
playSound(2);
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.orange),
),
TextButton(
onPressed: () {
playSound(3);
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.yellow),
),
TextButton(
onPressed: () {
playSound(4);
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.green),
),
TextButton(
onPressed: () {
playSound(5);
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.teal),
),
TextButton(
onPressed: () {
playSound(6);
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.blue),
),
TextButton(
onPressed: () {
playSound(7);
},
child: Text(''),
style: TextButton.styleFrom(backgroundColor: Colors.purple),
)
],
),
),
),
);
}
}
Durch die Verwendung einer playSound Funktion konnten wir die Anzahl an Codezeilen bereits ein bisschen reduzieren und die in unserem Programmcode wiederholt verwendete Funktionalität gruppieren.