개발노트

13. [Flutter] 피아노 위젯 사용하기 본문

앱 개발/Flutter

13. [Flutter] 피아노 위젯 사용하기

mroh1226 2023. 4. 12. 15:29
반응형

Piano 위젯을 사용하여 건반을 이용한 앱을 만들 수 있습니다.

 

 

1. 아래 주소에서 piano 패키지를 받아 프로젝트에 설치해줍니다.

 

- 설치링크: https://pub.dev/packages/piano

 

piano | Flutter Package

Utilities and widgets for working with piano sheet music learning.

pub.dev

pubspec.yaml으로 위젯 설치


2. 아래와 같이 코드를 작성하고 빌드합니다.

import 'package:flutter/material.dart';
import 'package:flutter_tonetrainer/models/entity_dump.dart';
import 'package:piano/piano.dart';

class PageChord extends StatefulWidget {
  final String title, content;
  final Level level;
  final IconData iconData;
  const PageChord(
      {super.key,
      required this.title,
      required this.content,
      required this.level,
      required this.iconData});

  @override
  State<PageChord> createState() => _PageChordState();
}

class _PageChordState extends State<PageChord> {
  final List<String> tappedNote = [];

  void isTappedNote(NotePosition position) {
    String str =
        position.name.toString().substring(0, position.name.length - 1);
    if (!tappedNote.contains(str)) {
      tappedNote.add(str);
    }
    setState(() {});
  }

  String getTappedNote() {
    String str = '';
    for (int i = 0; i < tappedNote.length; i++) {
      str += '${tappedNote[i]} ';
    }
    return str.substring(0, str.length - 1);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 30),
          child: Expanded(
            child: Column(
              children: [
                Hero(
                  tag: widget.title,
                  child: Container(
                    padding: const EdgeInsets.symmetric(
                        horizontal: 20, vertical: 20),
                    decoration: BoxDecoration(
                        color: Colors.amber.shade800,
                        borderRadius:
                            const BorderRadius.all(Radius.elliptical(20, 20))),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Icon(
                          widget.iconData,
                          size: 30,
                        ),
                        Text(
                          widget.title,
                          style: const TextStyle(
                              fontSize: 30, fontWeight: FontWeight.bold),
                        )
                      ],
                    ),
                  ),
                ),
                const SizedBox(
                  height: 20,
                ),
                Column(
                  children: [
                    Container(
                        decoration:
                            BoxDecoration(color: Colors.lightGreen.shade700),
                        width: 400,
                        height: 150,
                        child: InteractivePiano(
                            noteRange: NoteRange.forClefs([Clef.Treble]),
                            highlightColor: Colors.greenAccent.shade700,
                            onNotePositionTapped: (position) =>
                                isTappedNote(position))),
                  ],
                ),
                Container(
                  padding: const EdgeInsets.all(30),
                  child: Text(
                    tappedNote.isEmpty ? '선택' : getTappedNote(),
                    style: const TextStyle(fontSize: 30),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

설명.1 피아노 건반 위젯 사용하기

 
                        child: InteractivePiano(
                            noteRange: NoteRange.forClefs([Clef.Treble]),
                            highlightColor: Colors.greenAccent.shade700,
                            onNotePositionTapped: (position) =>
                                isTappedNote(position))),
 

- InteractivePiano 위젯을 선언하여 피아노 건반을 불러옵니다.

- noteRange: 로 건반의 범위를 설정합니다.

- onNotePositionTapped: 건반 클릭 시 position 이라는 NotePosition을 반환하며, 이벤트를 줄 수 있는 함수

*더 많은 속성들의 정보는 pub dev에서 확인하시면됩니다.

  void isTappedNote(NotePosition position) {
    String str =
        position.name.toString().substring(0, position.name.length - 1);
    if (!tappedNote.contains(str)) {
      tappedNote.add(str);
    }
    setState(() {});
  }

 

- tappedNoteList<String> 형 변수로 클릭된 note이름을 담기위해 생성하였습니다.

- 이미 클릭된 note는 추가하지않기 위해 contains() 로 확인합니다.

- 옥타브 이름을 빼기 위해서 substring을 사용하여 전체길이 -1 해주었습니다.

- 변경된 tappedNote를 노출 시키기위해 setState를 해줍니다.

 

 

설명.2 클릭된 건반 이름 가져오기

      
                Container(
                  padding: const EdgeInsets.all(30),
                  child: Text(
                    tappedNote.isEmpty ? '선택' : getTappedNote(),
                    style: const TextStyle(fontSize: 30),
                  ),
                )

- Text 위젯을 사용하여 tappedNote를 노출 시킴니다.

- List에 item이 없는 Null일 때는 '선택' 이 나오도록하며, item이 하나라도 있을 경우 getTappedNote()로 return 되는 String 값을 노출 시킵니다.

  String getTappedNote() {
    String str = '';
    for (int i = 0; i < tappedNote.length; i++) {
      str += '${tappedNote[i]} ';
    }
    return str.substring(0, str.length - 1);
  }

- getTappedNote 메소드로 tappedNote의 item 값들을 한줄로 나열하여 String형으로 return 합니다.

- for문으로 str에 저장하고 구분지어줄 공백을 함께 사용하기 위해 '${tappedNote[i]} ' 달러표시와 괄호를 사용합니다.

 


빌드된 모습.

빌드

 

반응형
Comments