Creating a Battery Indicator Watch Face for Garmin

Today, I want to show you how to create a very simple battery indicator in Garmin. I want to create a label that shows the current battery percentage which also changes colour depending on the percentage level.

So, I’ll start by creating a new label in the watch that I will use. This is my layout.xml:

<layout id="WatchFace">
<label id="BatteryLabel" x="center" y="center" font="Graphics.FONT_NUMBER_THAI_HOT" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_WHITE" />
</layout>

Now, in the View.mc file I will use this label to add the battery percentage and assign a colour based on that percentage.

First, I will paste in my updateDisplayObject method to update the label text:

//Update the display object text
function updateDisplayObject(updateObject, updateText){
var _viewObject = View.findDrawableById(updateObject) as Text;
_viewObject.setText(updateText);
}

I will then create a method to update the battery label’s text colour based on the battery percentage. This will need to take in the battery percentage as a parameter:

//Update the battery text color
function updateBatteryTextColor(updateBatPerc){
var _color = Graphics.COLOR_GREEN;
//Setting battery label color based on percentage
if (updateBatPerc > 75){
_color = Graphics.COLOR_DK_GREEN;
}
if (updateBatPerc < 75 && updateBatPerc >= 25){
_color = Graphics.COLOR_YELLOW;
}
if (updateBatPerc < 25){
_color = Graphics.COLOR_RED;
}
var _viewObject = View.findDrawableById("BatteryLabel");
_viewObject.setColor(_color);
}

From the above code, you can see I am assigning a specific color based on the batter percentage on a three tier system. The label colour will be based on the following rules:

ValuesColor
Greater than 75%Green
Lower than 75% and higher than or equal to 25%Yellow
Lower than 25%Red
Battery label colour table

I can now update the onUpdate method to use the above methods to show the battery indicator correctly. This is what the onUpdate method looks like:

// Update the view
function onUpdate(dc as Dc) as Void {
//Get and show the current battery percentage
var pwr = System.getSystemStats().battery;
var batStr = Lang.format( "$1$%", [ pwr.format( "%2d" ) ] );
updateDisplayObject("BatteryLabel", batStr);
//Update battery text color
updateBatteryTextColor(pwr);
// Call the parent onUpdate function to redraw the layout
View.onUpdate(dc);
}

After all that, you can see the watch face showing the correct three colours below:

Red battery indicator
Yellow battery indicator
Green battery indicator

Enjoy! 🎉

Creating a Simple Garmin Watch Face

So, I recently got into running and picked up a bargain Garmin watch. I looked on the marketplace for a simple watch face that had the attributes I wanted. I found nothing that suited my needs.

The apps from the app store were often too complex looking or lacked functionality.

This is where I started researching how to create a custom watch face and maybe even post it to the marketplace if possible. I learnt that Garmin uses Monkey C along with their SDK to create everything from watch faces to apps.

First things first, you need to setup the environment and download the SDK: https://developer.garmin.com/connect-iq/sdk/

Once setup, lets open Visual Studio Code and open the command palette using Ctrl+Alt+P. In this prompt, we want to search for the Monkey C: New Project option. It will then ask for the name of the project and the type. For this example, I will select a Simple Watch Face and set the API level to the lowest value.

This will build the project structure and create a base watch face to work from.

We now need to add supported products to the project. My watch is the Garmin Forerunner 735XT but you can use whichever watch you have. Use the command palette again and use the Monkey C: Edit Products option. In that dropdown, select all the watches you want to support and build for.

Now we can hit F5 and run the watch face in the virtual watch:

The prebuilt project from Garmin

In this post, I’m going to build a watch face similar to the below design:

Simple watch face design concept

First, lets edit the layout.xml to build the design of the watch face. This file is in Resources -> Layouts.

Remove the default label from the XML file and lets build the 4 new labels required for our battery percentage, steps, current time and todays date.

The layouts are fairly easy to follow, each label requires the following attributes:

AttributeExplanationPossible Values
idThe name of the label. This will be used in the code to update the value.Any string value starting with a capital letter. E.g. TestLabel
xThe horizontal positioning of the label. This can be a pixel value or the predefined values.left, center, right, pixel value, or a percentage
yThe vertical positioning of the label. This can be a pixel value or the predefined values.top, center, bottom, pixel value, or a percentage
fontThe font to use on the label. These are predefined.All options are documented in the API docs. We are only using values from API level 1.0.0 for now:

https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics.html
justificationHow the text should position itself in the space provided.TEXT_JUSTIFY_RIGHT,
TEXT_JUSTIFY_CENTER,
TEXT_JUSTIFY_LEFT,
TEXT_JUSTIFY_VCENTER
colorThe colour of the textAll options are documented in the API docs:

https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics.html

So my new layout.xml file will look like this:

<layout id="WatchFace">
<label id="TimeLabel" x="center" y="center" font="Graphics.FONT_NUMBER_THAI_HOT" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_WHITE" />
<label id="BatteryPercentageLabel" x="center" y="top" font="Graphics.FONT_MEDIUM" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_LT_GRAY"/>
<label id="StepsLabel" x="center" y="10%" font="Graphics.FONT_MEDIUM" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_LT_GRAY"/>
<label id="DateLabel" x="center" y="bottom" font="Graphics.FONT_MEDIUM" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_LT_GRAY"/>
</layout>

Now that the layout is built, we need to build the functionality in the backend to update the view. Open the watch face _View.mc file. This can be found in Source -> watchface_View.mc.

First, lets add a required using statement at the top. Add the following line:

using Toybox.Time.Gregorian as Calendar;

I will also create a new method for updating the view. This method will take in the string ID of the label as well as the new value:

//Update the display object text
function updateDisplayObject(updateObject, updateText){
var _viewObject = View.findDrawableById(updateObject) as Text;
_viewObject.setText(updateText);
}

We can now use the above method to update the view.

We will now head over to the onUpdate method to update the view.

Now, lets work on building the required data and formatting it before updating the view. You can see below how I work through each of the four required sections and use the above updateDisplayObject method to update the view:

// Get and show the current time
var clockTime = System.getClockTime();
var timeString = Lang.format("$1$:$2$", [clockTime.hour, clockTime.min.format("%02d")]);
updateDisplayObject("TimeLabel", timeString);
//Get and show the current battery percentage
var pwr = System.getSystemStats().battery;
var batStr = Lang.format( "$1$%", [ pwr.format( "%2d" ) ] );
updateDisplayObject("BatteryPercentageLabel", batStr);
//Get and show the steps data
var stepCountString = ActivityMonitor.getInfo().steps.toString();
updateDisplayObject("StepsLabel", stepCountString);
//Get and show the date
var now = Time.now();
var info = Calendar.info(now, Time.FORMAT_LONG);
var dateString = Lang.format("$1$ $2$ $3$", [info.day_of_week, info.day, info.month]);
updateDisplayObject("DateLabel", dateString);

Now, when we hit F5 to run the watch face, you can see how the display has changed and we have built the watch layout:

The built simple watch layout

Hope this helps someone out as the documentation is a little lacking. Enjoy! 🎉 🎉

Additional Notes – You can also confirm the languages your watch face will support by using the Monkey C: Edit Languages option.