As the title mentions, I'm currently creating a guitar application that is to include some information on basic notes and chords, a chord generator, and of course a guitar tuner. I've decided to start with what I believe is the hardest part and unfortunately making little to no progress.
I'd like to include a BottomNavigationBar to navigate between these three tools, each taking up one page. I can get the navigation to work while using StatelessWidget, but once I start using _TunerState for recording purposes I start receiving errors.
I've managed to get this tool working in a separate application using just the main.dart but integrating that solution into my project is proving difficult.
What I intend to do is use the _TunerState class to initialize and start the flutter_fft recorder, which will listen for changes in the mic input and output information such as frequency, note, etc.
Below is my home_widget.dart, in charge of the navigation, or at least that's what I'm trying to do with it
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State {
int currentTab = 0;
late Widget currentPage;
late Fretboard fretboard;
late ChordGen chordGen;
late Tuner tuner;
late List<Widget> pages;
@override
void initState() {
fretboard = Fretboard();
chordGen = ChordGen();
tuner = Tuner();
pages = [fretboard, chordGen, tuner];
currentPage = fretboard;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle(statusBarColor: Colors.transparent),
toolbarHeight: -24,
),
body: currentPage,
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (int index) {
setState(() {
currentTab = index;
currentPage = pages[index];
});
},
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(GuitarIcons.two_music_notes, size: 30),
title: Text("Fretboard")),
BottomNavigationBarItem(
icon: Icon(GuitarIcons.generator, size: 30),
title: Text("Generator")),
BottomNavigationBarItem(
icon: Icon(GuitarIcons.sound_bars, size: 30),
title: Text("Tuner")),
],
),
);
}
}
And here is my tuner.dart, which needs to be Stateful for things like flutterFft.onRecorderStateChange.listen
class Tuner extends StatefulWidget {
@override
_TunerState createState() => _TunerState();
}
class _TunerState extends State<Home> {
double? frequency;
String? note;
int? octave;
bool? isRecording;
FlutterFft flutterFft = FlutterFft();
_initialize() async {
print("Starting recorder...");
// print("Before");
// bool hasPermission = await flutterFft.checkPermission();
// print("After: " hasPermission.toString());
// Keep asking for mic permission until accepted
while (!(await flutterFft.checkPermission())) {
flutterFft.requestPermission();
// IF DENY QUIT PROGRAM
}
// await flutterFft.checkPermissions();
await flutterFft.startRecorder();
print("Recorder started...");
setState(() => isRecording = flutterFft.getIsRecording);
flutterFft.onRecorderStateChanged.listen(
(data) => {
print("Changed state, received: $data"),
setState(
() => {
frequency = data[1] as double,
note = data[2] as String,
octave = data[5] as int,
},
),
flutterFft.setNote = note!,
flutterFft.setFrequency = frequency!,
flutterFft.setOctave = octave!,
print("Octave: ${octave!.toString()}"),
sleep(const Duration(milliseconds: 100))
},
one rror: (err) {
print("Error: $err");
},
onDone: () => {print("Isdone")});
}
@override
void initState() {
isRecording = flutterFft.getIsRecording;
frequency = flutterFft.getFrequency;
note = flutterFft.getNearestNote;
octave = flutterFft.getOctave;
super.initState();
_initialize();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Simple flutter fft example",
theme: ThemeData.dark(),
color: Colors.blue,
home: Scaffold(
backgroundColor: Colors.purple,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
isRecording!
? Text("Current note: ${note!}",
style: TextStyle(fontSize: 30))
: Text("Not Recording", style: TextStyle(fontSize: 35)),
isRecording!
? Text(
"Current frequency: ${frequency!.toStringAsFixed(2)}",
style: TextStyle(fontSize: 30))
: Text("Not Recording", style: TextStyle(fontSize: 35))
],
),
),
));
}
}
So when I attempt to run the application on my Android Emulator I receive this error message
======== Exception caught by widgets library =======================================================
The following assertion was thrown building _BodyBuilder:
StatefulWidget.createState must return a subtype of State<Tuner>
The createState function for Tuner returned a state of type _TunerState, which is not a
subtype of State<Tuner>, violating the contract for createState.
The relevant error-causing widget was:
Scaffold Scaffold:file:///C:.../guitar_app/lib/home_widget.dart:42:12
When the exception was thrown, this was the stack:
**followed by nearly 200 lines of error code....**
I've looked around online and just can't seem to find anything that quite fits this issue, but maybe I just don't know the answer when I see it....
If more information is required please let me know but hopefully I've included everything here. I'm pretty new to Flutter but have knowledge of most of the other typical languages, i.e., Java, JS, Python, HTML, etc.
Thanks in advance, any help is greatly appreciated, or any suggestions on a better approach would definitely be helpful too :)
CodePudding user response:
In your tuner.dart File the _TurnerState extends the Sate<Home>
but it needs to extend for example class _TunerState extends State<Turner>
.