Skip to main content

More Controls

In the following steps of the tutorial we will add some basic controls for the end users which will allow them to:

  • Enable/Disable the count-in
  • Enable/Disable the metronome
  • Enable/Disable the looping
  • Change the zoom level
  • Change the layout of the music sheet

The implementation will follow the same principle for all controls:

  1. We add the UI to the popup
  2. We add new properties to the viewmodel.
  3. We add event listeners to the UI and interact with the viewmodel.
  4. In the activity we listen to the viewmodel values and map them to the alphaTab API object

Toggle Control Style​

For the toggle controls we will add a small helper which will change the colors of the icon and text according to the check state. This code should not act as a reference how to properly style controls in android but is rather a simplistic approach for this tutorial.

In this file we add some new colors for our buttons which will toggle some features in an on/off fashion.

<color name="checkedIconColor">#FF436d9d</color>
<color name="uncheckedIconColor">#7F436d9d</color>
<color name="checkedTextColor">#FF000000</color>
<color name="uncheckedTextColor">#7F000000</color>

Count-In​

The count-in will become relevant when we activate the player in the next step, but we can already create the control which will set the count-in volume based on the toggle button state.

<!-- After openFile button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/countIn"
style="@style/PopupButton"
android:checkable="true"
app:icon="@drawable/baseline_hourglass_empty_24"
android:text="Count-In" />

Metronome​

The metronome will become relevant when we activate the player in the next step, but we can already create the control which will set the metronome volume based on the toggle button state.

<com.google.android.material.button.MaterialButton
style="@style/PopupButton"
android:checkable="true"
android:id="@+id/metronome"
app:icon="@drawable/baseline_edit_square_24"
android:text="Metronome"/>

Looping​

Again nothing new here, rinse and repeat to extend the UI and map the UI state ultimately to the API object:

<com.google.android.material.button.MaterialButton
style="@style/PopupButton"
android:checkable="true"
android:id="@+id/looping"
app:icon="@drawable/baseline_repeat_24"
android:text="Looping" />

Zoom​

As alphaTab can change the scale in which the music sheet is rendered, we offer the user a popup menu to change this scale.

<com.google.android.material.button.MaterialButton
style="@style/PopupButton"
android:id="@+id/zoom"
app:icon="@drawable/baseline_zoom_in_24"
android:text="Zoom" />

Layout​

alphaTab can either render the music sheet in a page-like fashion that grows from top to bottom along the available width. Or it can show the music sheet in a horizontal scrolling fashion.

These options are also offered to the user via another popup menu. To actually apply the user selection we will again just fill the user input into the settings object and trigger an update just like for the zoom level:

<com.google.android.material.button.MaterialButton
style="@style/PopupButton"
android:id="@+id/layout"
app:icon="@drawable/baseline_view_quilt_24"
android:text="Layout" />

Result​

That was already it. As you can see now, it is typically the same task over and over to extend your app with new functionalities. The biggest complexity is to identify how you want to build your UI towards your user. Using your Android development expertise you give the user options to change the settings as desired. After that is "only" understanding how to tell alphaTab how to respect those settings. Often the idea for new features start in the Settings and API reference to see what functionalities are offered.

Final Files​

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="HardcodedText"
tools:context=".MainActivity">

<alphaTab.AlphaTabView
android:id="@+id/alphatab"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:padding="6dp"
android:background="#436d9d"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">

<LinearLayout
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/controls"
android:orientation="vertical"
>
<TextView
android:id="@+id/trackName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Track Name"
android:textColor="@color/white" />
<TextView
android:id="@+id/songName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Song Name - Artist Name"
android:textStyle="bold"
android:textColor="@color/white"
/>

</LinearLayout>

<LinearLayout
android:id="@+id/controls"
android:layout_alignParentEnd="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<ImageButton
android:id="@+id/playPause"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@null"
android:textColor="@color/white"
android:paddingHorizontal="7dp"
android:contentDescription="Play/Pause"
android:src="@drawable/baseline_play_arrow_24" />

</LinearLayout>

</RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>