Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A Kotlin multi-platform view library for displaying stringed instrument chord diagrams

License

NotificationsYou must be signed in to change notification settings

chRyNaN/chords

Repository files navigation

An easily customizable Kotlin multi-platform View to display guitar (and other stringed instrument) chords. Simple touse and beautifully designed.

Current Version:GitHub tag (latest by date)

Sample ScreenshotSample Screenshot

This library has been updated significantly from its original version and the process is detailed inthisblog post which was featured in Android Weeklyissue #398.Badge

Building the library

The library is provided throughRepsy.io. Checkoutthereleases page to get the latest version.
GitHub tag (latest by date)

Repository

repositories {    maven { url= uri("https://repo.repsy.io/mvn/chrynan/public") }}

Dependencies

core:

implementation("com.chrynan.chords:chords-core:VERSION")

compose:

implementation("com.chrynan.chords:chords-compose:VERSION")

Usage

There are a few main components to using the library:

  • ChordWidget is theChordView implementation that displays the chord.
  • ChordChart is a class that represents information about the chord chart that will be displayed.
  • Chord is a class that represents the markers on a chord that will be displayed.

Creating an instance ofChordWidget

Android:

<!-- Specify an exact size (MATCH_PARENT, MATCH_CONSTRAINTS, DP value).--><com.chrynan.chords.widget.ChordWidgetandroid:id="@+id/chordWidget"android:layout_width="match_parent"android:layout_height="wrap_content"/>

Kotlin JS:

val widget=ChordWidget(htmlCanvas)

Jetpack Compose:

ChordWidget(    modifier=Modifier.size(width=200.dp, height=200.dp),    chord= chord,    chart= chart)

Assigning aChordChart to aChordWidget

chordWidget?.chart=ChordChart(    fretStart=FretNumber(1),    fretEnd=FretNumber(2),    stringCount=6,    stringLabels=setOf(StringLabel(string=StringNumber(1), label="e"),StringLabel(string=StringNumber(2), label="B"),StringLabel(string=StringNumber(3), label="G"),StringLabel(string=StringNumber(4), label="D"),StringLabel(string=StringNumber(5), label="A"),StringLabel(string=StringNumber(6), label="E")    ))

Creating a Chord using the DSL

val chord= chord("G") {+ChordMarker.Note(        fret=FretNumber(3),        finger=Finger.MIDDLE,        string=StringNumber(6)    )+ChordMarker.Note(        fret=FretNumber(2),        finger=Finger.INDEX,        string=StringNumber(5)    )+ChordMarker.Open(string=StringNumber(4))+ChordMarker.Open(string=StringNumber(3))+ChordMarker.Note(        fret=FretNumber(3),        finger=Finger.RING,        string=StringNumber(2)    )+ChordMarker.Note(        fret=FretNumber(3),        finger=Finger.PINKY,        string=StringNumber(1)    )}

Assigning aChord to aChordWidget

chordWidget?.chord= chord

Note: This library doesn't try to coerce values to fit into a chart or exclude values that exceed the chart bounds.If theChordChart andChord have inconsistent values, theChordWidget may look peculiar. It's important for theuser of the library to properly handle coordinating the different components.

Parsing Chords from other formats

TheChordParser interface takes in an input type and outputs aChordParseResult. This interface can be implementedfor different format input types. There are a couple providedChordParser implementations.

AsciiChordParser:

AsciiChordParser parses aString input of an ASCII Chord Diagram and outputs aChordParseResult containingaChord.

val chordDiagram="""            C    e |-----0------|    B |-----1------|    G |-----0------|    D |-----2------|    A |-----3------|    E |------------|""".trimIndent()val parser=AsciiChordParser()launch {// parse() is a suspending function and needs to be called from another suspending// function or a coroutineval result= parser.parse(chordDiagram)val chord:Chord= result.chordval stringLabels:Set<StringLabel>= result.stringLabelsval baseFret:FretNumber?= result.baseFret}

ChordProParser:

ChordProParser parses aString input of a Chord Pro (Chord or Define) Directive and outputs aChordParseResultcontaining aChord.

val chordDiagram="{define: Bes base-fret 1 frets 1 1 3 3 3 1 fingers 1 1 2 3 4 1}"val parser=ChordProParser()launch {// parse() is a suspending function and needs to be called from another suspending// function or a coroutineval result= parser.parse(chordDiagram)val chord:Chord= result.chordval stringLabels:Set<StringLabel>= result.stringLabelsval baseFret:FretNumber?= result.baseFret}

Customizing the appearance

ChordWidget implements theChordView interface which contains properties to alter the appearance of the view.

ChordView:

interfaceChordView {...var fitToHeight:Booleanvar showFretNumbers:Booleanvar showFingerNumbers:Booleanvar stringLabelState:StringLabelStatevar mutedStringText:Stringvar openStringText:Stringvar fretColor:ColorIntvar fretLabelTextColor:ColorIntvar stringColor:ColorIntvar stringLabelTextColor:ColorIntvar noteColor:ColorIntvar noteLabelTextColor:ColorInt...}

Updating properties directly on ChordWidget:

chordWidget?.noteColor=Color.BLUEchordWidget?.openStringText="o"

Note: That in Kotlin JS, you have to explicitly call therender() function after updating properties ontheChordWidget.

Updating properties using a ViewModel and Binder:

val binder=ChordViewBinder(chordWidget)val viewModel=ChordViewModel(    fretColor=Color.BLACK,    fretLabelTextColor=Color.WHITE,    stringLabelTextColor=Color.BLACK,    stringColor=Color.BLACK,    noteColor=Color.BLACK,    noteLabelTextColor=Color.WHITE)binder.bind(viewModel)

Note: That in Kotlin JS, there is a convenience functionChordViewBinder.bindAndRender() which will bind theproperties from theChordViewModel to theChordWidget and callrender().

Updating properties in Android XML:

<com.chrynan.chords.widget.ChordWidgetandroid:id="@+id/chordWidget"android:layout_width="200dp"android:layout_height="300dp"app:stringLabelState="label"app:showFretNumbers="false"/>

Available Android XML Attributes:

<attrname="fretColor"format="color"/><attrname="fretLabelTextColor"format="color"/><attrname="stringColor"format="color"/><attrname="stringLabelTextColor"format="color"/><attrname="noteColor"format="color"/><attrname="noteLabelTextColor"format="color"/><attrname="mutedStringText"format="string"/><attrname="openStringText"format="string"/><attrname="showFingerNumbers"format="boolean"/><attrname="showFretNumbers"format="boolean"/><attrname="stringLabelState"format="enum"><enumname="number"value="0"/><enumname="label"value="1"/><enumname="hide"value="2"/></attr><attrname="fitToHeight"format="boolean"/><attrname="fretLabelTypeface"format="reference"/><attrname="noteLabelTypeface"format="reference"/><attrname="stringLabelTypeface"format="reference"/>

Selectable Chord names in Text using Android Spans

The library comes with aChordSpan which allows the pairing of text with aChord. And when theChordSpan isselected, a listener is alerted with theChord.

Adding aChordSpan to aTextView:

val text=SpannableString("G")val span=ChordSpan(chord,this)// "this" refers to the listenertext.setSpan(span,0,1,Spannable.SPAN_INCLUSIVE_EXCLUSIVE)textView?.text= text// Need to specify LinkTouchMovementMethod as the movement method for clicks to worktextView?.movementMethod=LinkTouchMovementMethod()

Using DSL functions to add aChordSpan to aTextView:

val textBuilder= buildSpannableString {+chordSpan(chord, listener)+chordSpan("G", chord) {// Handle click event    }+styledChordSpan(chord, listener) {this.backgroundColor=Color.BLUE    }}textView?.text= textBuilder// Need to specify LinkTouchMovementMethod as the movement method for clicks to worktextView?.movementMethod=LinkTouchMovementMethod()

Listening toChord selected events:

classMainActivity :AppCompatActivity(),ChordSpan.ChordSelectedListener {overridefunonChordSpanSelected(chord:Chord) {// Perform action with chord    }}

Customizing theChordSpan appearance:

ChordSpan extends fromTouchableSpan which inherits fromTouchableSpanView and has the following customizableproperties:

var backgroundColor=Color.TRANSPARENTvar selectedBackgroundColor=Color.TRANSPARENTvar textColor=Color.BLUEvar selectedTextColor=Color.BLUEvar isUnderlined=falsevar isUnderlinedWhenSelected=falsevar textTypeface=Typeface.DEFAULTvar selectedTextTypeface=Typeface.DEFAULT

These properties can be changed on the span:

span.textColor=Color.RED

Passing Chords between Android components

The model classes are notParcelable because they are in a Kotlin multi-platform module and don't have access toAndroid Framework classes. But the Android library module does have wrapper classes that handle the serialization andde-serialization of theChord andChordChart models.

These classes areParcelableChordWrapper andParcelableChartWrapper. To passChord andChordChart betweencomponents, such as, in a Bundle, just wrap them with their respective wrapper models.

arguments=Bundle().apply {        putParcelable(KEY_CHORD,ParcelableChordWrapper(chord))        putParcelable(KEY_CHART,ParcelableChartWrapper(chart))    }

Then retrieve the wrappers just as you would with any other Parcelable object.

arguments?.getParcelable<ParcelableChordWrapper>(KEY_CHORD)arguments?.getParcelable<ParcelableChartWrapper>(KEY_CHART)

For convenience, there are extension functions on theBundle andIntent objects which handle the wrapping andunwrapping of theChord andChordChart objects.

Bundle:

arguments=Bundle().apply {        putChord(KEY_CHORD, chord)        putChordChart(KEY_CHART, chart)    }val chord= arguments?.getChord(KEY_CHORD)val chart= arguments?.getChordChart(KEY_CHART)

Intent:

intent.putChord(KEY_CHORD, chord)intent.putChordChart(KEY_CHART, chart)val chord= intent.getChordExtra(KEY_CHORD)val chart= intent.getChordChartExtra(KEY_CHART)

There is also a convenienceChordAndChart class (with similar Parcelable extension functions) for when both aChordand aChordChart need to be passed between Android components together.

val chordAndChart=ChordAndChart(chord= chord, chart= chordChart)// Bundlearguments= bundle.putChordAndChart(KEY_CHORD_AND_CHART, chordAndChart)arguments?.getChordAndChart(KEY_CHORD_AND_CHART)// Intentintent.putChordAndChartExtra(KEY_CHORD_AND_CHART, chordAndChart)intent.getChordAndChartExtra(KEY_CHORD_AND_CHART)

Samples

Checkout the sample modules for examples on using the library.

License

Copyright 2020 chRyNaNLicensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License at   http://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.

[8]ページ先頭

©2009-2025 Movatter.jp