flutter_piano_pro 0.2.0 copy "flutter_piano_pro: ^0.2.0" to clipboard
flutter_piano_pro: ^0.2.0 copied to clipboard

flutter_piano_pro is a Flutter package that provides a customizable piano widget.

example/lib/main.dart

import 'dart:convert';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter_piano_pro/flutter_piano_pro.dart';
import 'package:flutter_piano_pro/note_model.dart';
import 'package:flutter_piano_pro/note_names.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  double noteCount = 7;
  double width = 300;
  double height = 250;
  bool expand = true;
  int firstNote = 0;
  int firstNoteOctave = 3;
  NoteType noteType = NoteType.english;
  bool showNames = true;
  bool showOctaveNumbers = true;
  AudioCache audioCache = AudioCache(prefix: "assets/piano_sounds/");
  Map<int, AudioPlayer> audios = {};
  Map<int, int> pointerNoteNumber = {};

  Future loadCache() async {
    var folderPath = 'assets/piano_sounds/';
    var manifestContent = await rootBundle.loadString('AssetManifest.json');
    var manifestMap = json.decode(manifestContent);
    List<String> fileNames = manifestMap.keys
        .where((String key) => key.startsWith(folderPath))
        .map((String key) => key.replaceAll(folderPath, ''))
        .toList()
        .cast<String>();
    audioCache.loadAll(fileNames);
  }

  @override
  void initState() {
    for (var i = 0; i < 116; i++) {
      var noteIndex = (i) % 7;
      var octave = (((i) / 7).floor()).toInt();
      var note = NoteModel(
          name: NoteNames.generate(noteType)[noteIndex],
          octave: octave,
          noteIndex: noteIndex,
          isFlat: false);

      if (![0, 3].contains(noteIndex)) {
        var flatNote = note.copyWith(isFlat: true);
        audios[flatNote.midiNoteNumber] = AudioPlayer()
          ..audioCache = audioCache;
      }
      audios[note.midiNoteNumber] = AudioPlayer()..audioCache = audioCache;
    }
    loadCache();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    List<String> noteNames = NoteNames.generate(noteType);
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorSchemeSeed: Colors.brown),
      home: Scaffold(
        appBar: AppBar(title: const Text('Flutter Piano Pro')),
        body: ListView(
          children: [
            ListTile(
              title: const Text('Note Names'),
              trailing: SizedBox(
                width: 250,
                child: DropdownButton(
                    value: noteType,
                    items: List.generate(NoteType.values.length, (index) {
                      return DropdownMenuItem(
                          value: NoteType.values[index],
                          child: Text(NoteNames.generate(NoteType.values[index])
                              .toString()));
                    }),
                    onChanged: (value) => setState(() => noteType = value!)),
              ),
            ),
            const Divider(
              height: 0,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text('First Note'),
                    SizedBox(
                      child: DropdownButton(
                          value: firstNote,
                          items: List.generate(noteNames.length, (index) {
                            return DropdownMenuItem(
                                value: index,
                                child: Text(noteNames[index].toString()));
                          }),
                          onChanged: (value) =>
                              setState(() => firstNote = value!)),
                    ),
                  ],
                ),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    const Text('First Octave'),
                    SizedBox(
                      child: DropdownButton(
                          value: firstNoteOctave,
                          items: List.generate(noteNames.length, (index) {
                            return DropdownMenuItem(
                                value: index, child: Text(index.toString()));
                          }),
                          onChanged: (value) =>
                              setState(() => firstNoteOctave = value!)),
                    ),
                  ],
                ),
              ],
            ),
            const Divider(
              height: 0,
            ),
            ListTile(
              leading: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Text(
                    'Note Count',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                  Text(noteCount.round().toInt().toString()),
                ],
              ),
              trailing: SizedBox(
                width: 250,
                child: Slider(
                  divisions: 44,
                  max: 45,
                  min: 1,
                  value: noteCount,
                  onChanged: (value) => setState(() => noteCount = value),
                ),
              ),
            ),
            const Divider(
              height: 0,
            ),
            ListTile(
              leading: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Text(
                    'Height',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                  Text(height.round().toInt().toString()),
                ],
              ),
              trailing: SizedBox(
                width: 250,
                child: Slider(
                  divisions: 27,
                  max: 300,
                  min: 150,
                  value: height,
                  onChanged: (value) => setState(() => height = value),
                ),
              ),
            ),
            const Divider(
              height: 0,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text(
                      'Width',
                      style: TextStyle(fontWeight: FontWeight.bold),
                    ),
                    Text(width.round().toInt().toString()),
                  ],
                ),
                SizedBox(
                  width: 200,
                  child: Slider(
                    divisions: 50,
                    max: 5000,
                    min: 100,
                    value: width,
                    onChanged: expand
                        ? null
                        : (value) => setState(() => width = value),
                  ),
                ),
                Column(
                  children: [
                    const Text('Expand Vertical'),
                    Checkbox(
                        value: expand,
                        onChanged: (value) => setState(() => expand = value!)),
                  ],
                )
              ],
            ),
            const Divider(
              height: 0,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text('Names'),
                    Checkbox(
                        value: showNames,
                        onChanged: (value) =>
                            setState(() => showNames = value!)),
                  ],
                ),
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text('Octave'),
                    Checkbox(
                        value: showOctaveNumbers,
                        onChanged: (value) =>
                            setState(() => showOctaveNumbers = value!)),
                  ],
                ),
              ],
            ),
            PianoPro(
                onTapDown: (note, pointer) {
                  if (note == null) return;
                  pointerNoteNumber[pointer] = note.midiNoteNumber;
                  audios[note.midiNoteNumber]!.stop();
                  audios[note.midiNoteNumber]!
                      .play(AssetSource('0-${note.midiNoteNumber}.mp3'));
                },
                onTapUpdate: (note, pointer) {
                  if (note == null) return;

                  if (pointerNoteNumber.containsKey(pointer) &&
                      pointerNoteNumber[pointer] == note.midiNoteNumber) return;
                  pointerNoteNumber[pointer] = note.midiNoteNumber;
                  audios[note.midiNoteNumber]!.stop();
                  audios[note.midiNoteNumber]!
                      .play(AssetSource('0-${note.midiNoteNumber}.mp3'));
                },
                noteType: noteType,
                showNames: showNames,
                showOctaveNumber: showOctaveNumbers,
                expandHorizontal: expand,
                totalWidth: width,
                firstNote: firstNote,
                firstNoteOctave: firstNoteOctave,
                buttonHeight: height,
                noteCount: noteCount.round().toInt()),
          ],
        ),
      ),
    );
  }
}
9
likes
0
pub points
69%
popularity

Publisher

verified publishermelihhakanpektas.com

flutter_piano_pro is a Flutter package that provides a customizable piano widget.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter

More

Packages that depend on flutter_piano_pro