LoginSignup
6
3

More than 5 years have passed since last update.

[Flutter] ピアノアプリ作る。

Posted at

こんにちは。
皆さんはピアノを弾くこと。好きなんですか?
ピアノアプリ作ってみました。

sf2 file 必要です。
作って見た後、Flutterのまた感動受けました。!

image.png
image.png
image.png

Screenshot_1553007766.png

main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_midi/flutter_midi.dart';
import 'package:tonic/tonic.dart';

class PianoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: PianoMain(),
    );
  }
}

class PianoMain extends StatefulWidget {
  @override
  _PianoMainState createState() => _PianoMainState();
}

class _PianoMainState extends State<PianoMain> {
  double _widthRatio = 0.0;
  bool _showLabels = true;

  double get keyWidth => 80 + (80 * _widthRatio);

  @override
  void initState() {
    FlutterMidi.unmute();
    rootBundle.load('assets/sound/Wii_Grand_Piano.sf2').then((sf2) {
      FlutterMidi.prepare(sf2: sf2, name: "GeneralUser.sf2");
    });
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("piano App"),
      ),
      drawer: Drawer(
        child: SafeArea(
            child: ListView(
          children: <Widget>[
            Container(
              height: 20.0,
            ),
            ListTile(
              title: Text("Change Width"),
            ),
            Slider(
              activeColor: Colors.white,
              inactiveColor: Colors.red,
              min: 0.0,
              max: 1.0,
              value: _widthRatio,
              onChanged: (double value) => setState(() => _widthRatio = value),
            ),
            Divider(),
            ListTile(
              title: Text("Show Labels"),
              trailing: Switch(
                  value: _showLabels,
                  onChanged: (bool value) {
                    setState(() {
                      _showLabels = value;
                    });
                  }),
            ),
            Divider(),
          ],
        )),
      ),
      body: ListView.builder(
        itemBuilder: (context, index) {
          final int i = index * 12;

          return SafeArea(
            child: Stack(
              children: <Widget>[
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    _buildKey(24 + i, false),
                    _buildKey(26 + i, false),
                    _buildKey(28 + i, false),
                    _buildKey(29 + i, false),
                    _buildKey(31 + i, false),
                    _buildKey(33 + i, false),
                    _buildKey(35 + i, false),
                  ],
                ),
                Positioned(
                  left: 0.0,
                  right: 0.0,
                  bottom: 100,
                  top: 0.0,
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Container(
                        width: keyWidth * 0.5,
                      ),
                      _buildKey(25 + i, true),
                      _buildKey(27 + i, true),
                      Container(
                        width: keyWidth,
                      ),
                      _buildKey(30 + i, true),
                      _buildKey(32 + i, true),
                      _buildKey(34 + i, true),
                      Container(
                        width: keyWidth * 0.5,
                      ),
                    ],
                  ),
                )
              ],
            ),
          );
        },
        itemCount: 7,
        scrollDirection: Axis.horizontal,
      ),
    );
  }

  Widget _buildKey(int i, bool param1) {
    final pitchName = Pitch.fromMidiNumber(i).toString();
    final pianoKey = Stack(
      children: <Widget>[
        Semantics(
          button: true,
          hint: pitchName,
          child: Material(
            borderRadius: BorderRadius.only(
                bottomLeft: Radius.circular(10.0),
                bottomRight: Radius.circular(10.0)),
            color: param1 ? Colors.black : Colors.white,
            child: InkWell(
              borderRadius: BorderRadius.only(
                  bottomLeft: Radius.circular(10.0),
                  bottomRight: Radius.circular(10.0)),
              highlightColor: Colors.grey,
              onTap: () {},
              onTapDown: (_) => FlutterMidi.playMidiNote(midi: i),
            ),
          ),
        ),
        Positioned(
            left: 0.0,
            right: 0.0,
            bottom: 20.0,
            child: _showLabels
                ? Text(
                    pitchName,
                    textAlign: TextAlign.center,
                    style:
                        TextStyle(color: !param1 ? Colors.black : Colors.white),
                  )
                : Container()),
      ],
    );
    if (param1) {
      return Container(
        width: keyWidth,
        color: Colors.black,
        margin: EdgeInsets.symmetric(horizontal: 2.0),
        padding: EdgeInsets.symmetric(horizontal: keyWidth * 0.1),
        child: Material(
          elevation: 6.0,
          borderRadius: BorderRadius.only(
              bottomLeft: Radius.circular(10.0),
              bottomRight: Radius.circular(10.0)),
          shadowColor: Color(0x802196f3),
          child: pianoKey,
        ),
      );
    }

    return Container(
      width: keyWidth,
      color: Colors.white,
      margin: EdgeInsets.symmetric(horizontal: 2.0),
      child: pianoKey,
    );
  }
}
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3