chord_diagrams 0.7.0
chord_diagrams: ^0.7.0 copied to clipboard
Fast guitar and ukulele chord diagrams from simple chord labels.
import 'package:flutter/material.dart';
import 'package:chord_diagrams/chord_diagrams.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await ChordDiagrams.ensureInitialized();
runApp(const ChordDiagramsExampleApp());
}
class ChordDiagramsExampleApp extends StatelessWidget {
const ChordDiagramsExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'chord_diagrams demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFFD8A84F),
brightness: Brightness.dark,
),
scaffoldBackgroundColor: const Color(0xFF101820),
),
home: const DemoHome(),
);
}
}
class DemoHome extends StatefulWidget {
const DemoHome({super.key});
@override
State<DemoHome> createState() => _DemoHomeState();
}
class _DemoHomeState extends State<DemoHome> {
Instrument _instrument = Instrument.guitar;
String _note = 'G';
String _suffix = '';
int _position = 0;
bool _showAllPositions = false;
bool _showAllChords = false;
late final List<String> _notes = ChordDiagrams.getNotes();
List<String> get _availableSuffixes =>
ChordDiagrams.getSuffixes(_note, instrument: _instrument);
String get _chord => '$_note$_suffix';
int get _positionCount =>
ChordDiagrams.getPositionCount(_chord, instrument: _instrument);
void _selectInstrument(Instrument instrument) {
setState(() {
_instrument = instrument;
if (!_availableSuffixes.contains(_suffix)) _suffix = '';
if (_position >= _positionCount) _position = 0;
});
}
void _selectNote(String note) {
setState(() {
_note = note;
if (!_availableSuffixes.contains(_suffix)) _suffix = '';
if (_position >= _positionCount) _position = 0;
});
}
void _selectSuffix(String suffix) {
setState(() {
_suffix = suffix;
if (_position >= _positionCount) _position = 0;
});
}
Widget _buildChip({
required String label,
required bool selected,
required VoidCallback onPressed,
}) {
return FilterChip(
label: Text(label),
selected: selected,
showCheckmark: false,
onSelected: (_) => onPressed(),
backgroundColor: const Color(0xFF18232C),
selectedColor: const Color(0xFFD8A84F),
side: BorderSide(
color: selected ? const Color(0xFFD8A84F) : const Color(0xFF35505F),
),
labelStyle: TextStyle(
color: selected ? const Color(0xFF101820) : Colors.white,
fontWeight: FontWeight.w600,
fontSize: 13,
),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: const VisualDensity(horizontal: -2, vertical: -2),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
);
}
@override
Widget build(BuildContext context) {
final suffixes = _availableSuffixes;
return Scaffold(
appBar: AppBar(
title: const Text('chord_diagrams demo'),
centerTitle: false,
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SegmentedButton<Instrument>(
segments: const [
ButtonSegment(value: Instrument.guitar, label: Text('Guitar')),
ButtonSegment(value: Instrument.ukulele, label: Text('Ukulele')),
],
selected: {_instrument},
onSelectionChanged: (s) => _selectInstrument(s.first),
style: ButtonStyle(
backgroundColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return const Color(0xFFD8A84F);
}
return const Color(0xFF18232C);
}),
foregroundColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return const Color(0xFF101820);
}
return Colors.white;
}),
),
),
const SizedBox(height: 12),
Wrap(
spacing: 6,
runSpacing: 6,
children: _notes.map((note) {
return _buildChip(
label: note,
selected: _note == note,
onPressed: () => _selectNote(note),
);
}).toList(),
),
const SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 8,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
DropdownButton<String>(
value: suffixes.contains(_suffix) ? _suffix : '',
dropdownColor: const Color(0xFF1C2A36),
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 14,
),
underline: Container(height: 1, color: const Color(0xFF35505F)),
items: suffixes.map((s) {
return DropdownMenuItem(
value: s,
child: Text(s.isEmpty ? 'major' : s),
);
}).toList(),
onChanged: (v) {
if (v != null) _selectSuffix(v);
},
),
...List.generate(_positionCount, (i) {
return _buildChip(
label: '$i',
selected: !_showAllPositions && !_showAllChords && _position == i,
onPressed: () => setState(() {
_showAllPositions = false;
_showAllChords = false;
_position = i;
}),
);
}),
_buildChip(
label: 'All Positions',
selected: _showAllPositions,
onPressed: () => setState(() {
_showAllPositions = !_showAllPositions;
_showAllChords = false;
}),
),
_buildChip(
label: 'All Chords',
selected: _showAllChords,
onPressed: () => setState(() {
_showAllChords = !_showAllChords;
_showAllPositions = false;
}),
),
],
),
const SizedBox(height: 16),
if (_showAllPositions)
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 160,
childAspectRatio: 0.8,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
),
itemCount: _positionCount,
itemBuilder: (context, index) {
return ChordDiagram(
chord: _chord,
position: index,
instrument: _instrument,
);
},
),
)
else if (_showAllChords)
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 160,
childAspectRatio: 0.8,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
),
itemCount: suffixes.length,
itemBuilder: (context, index) {
final s = suffixes[index];
return ChordDiagram(
chord: '$_note$s',
instrument: _instrument,
);
},
),
)
else ...[
SelectableText(
'ChordDiagram(chord: "$_chord", '
'instrument: Instrument.${_instrument.name}, '
'position: $_position)',
style: const TextStyle(
fontFamily: 'Menlo',
fontSize: 13,
color: Colors.white54,
),
),
const SizedBox(height: 16),
Expanded(
child: Center(
child: ChordDiagram(
chord: _chord,
position: _position,
instrument: _instrument,
width: 300,
),
),
),
],
],
),
),
);
}
}