Checkbox controls in Fitbit OS5
Fitbit OS5
Last year Fitbit announced OS5 and during this year I have ported two of my apps from OS4 to OS5: wrist-list and Timestyle.
While I was porting them one of the things that tripped me up was that OS5 does not have a documented checkbox widget
Now I have ported both apps I have pulled out my implementation of checkbox so that it is relativity easy to add to other apps.
Checkbox Control
These are the steps to add a checkbox control to a Fitbit OS5 app. Full source code can be found in the timestyle repo
widget.defs
In widget.defs
add this line
1
2
3
4
5
6
7
<svg>
<defs>
<!-- other application imports -->
<!-- my implementation of checkboxes in tile list -->
<link rel="import" href="checkbox_tile_list.defs" />
</defs>
</svg>
checkbox_tile_list.defs
checkbox_tile_list.defs
should contain
1
2
3
4
5
6
7
8
9
10
11
12
13
<svg>
<defs>
<symbol id="checkbox-tile-item" href="#tile-list-item" class="list-item-checkbox" height="55" focusable="false" pointer-events="none" system-events="all">
<rect id="item-background" x="0" y="0" width="100%" height="100%"/>
<textarea id="item-text" x="10" y="11" text-length="50" width="100% - 48" height="100%">item-text</textarea>
<rect id="check-rect-border" x="100% - 44" y="13" width="30" height="30" />
<rect id="check-rect" x="100% - 43" y="14" width="28" height="28" />
<image id="check-on-img" x="100% - 43" y="14" width="28" height="28" href="images/check_on.png" />
<rect id="tile-divider-bottom" class="tile-divider-bottom" />
<rect id="touch" pointer-events="all" />
</symbol>
</defs>
</svg>
You will also need the file images/check_on.png
, the path is relative to the .defs
files and the image comes from the Fitbit design assets
style.css
Next add these lines to your style.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* checkbox tile items */
.list-item-checkbox textarea {
fill: #FFFFFF;
}
.list-item-checkbox #check-rect-border {
fill: #FFFFFF;
}
.list-item-checkbox #check-on-img {
fill: #FFFFFF;
display: none;
}
#touch {
width: 100%;
height: 100%-6;
x: 0;
y: 0;
opacity: 0;
}
your_screen.view
In your .view
file you can add checkboxes like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<svg id="settings-screen" display="none">
<use id="settings-list" href="#tile-list">
<var id="reorder-enabled" value="0"/>
<var id="peek-enabled" value="0" />
<use id="settings-suppress-alert" href="#checkbox-tile-item" class="checkbox-tile-item">
<set href="item-text" attributeName="text-buffer" to="Suppress alerts" />
</use>
<use id="settings-override-time" href="#checkbox-tile-item" class="checkbox-tile-item">
<set href="item-text" attributeName="text-buffer" to="Override time" />
</use>
</use>
</svg>
index.js
And finally they need to be hooked up to code in your javascript file like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
let imageSuppressAlerts = null;
let imageOverrideTime = null;
// menu panel
let list = document.getElementById("settings-list");
let checkboxItems = list == null ? null : list.getElementsByClassName("checkbox-tile-item");
if (checkboxItems != null) {
checkboxItems.forEach((element, index) => {
let checkImage = element.getElementById("check-on-img");
if (checkImage != null) {
switch (index) {
case 0: // suppress alerts
imageSuppressAlerts = checkImage;
break;
case 1: // override time
imageOverrideTime = checkImage;
break;
}
}
let touch = element.getElementById("touch");
touch.onclick = (evt) => {
switch (index) {
case 0: // suppress alerts
toggleSuppressAlerts(imageSuppressAlerts);
break;
case 1: // override time
toggleOverrideTime(imageOverrideTime);
break;
}
}
});
function toggleSuppressAlerts(chkImage) {
deviceSettings.setSuppressAlerts(!deviceSettings.isSuppressAlerts());
setupCheckImageDisplay(chkImage, deviceSettings.isSuppressAlerts());
};
function toggleOverrideTime(chkImage) {
deviceSettings.setOverrideTime(!deviceSettings.isOverrideTime());
setupCheckImageDisplay(chkImage, deviceSettings.isOverrideTime());
};
function setupCheckImageDisplay(image, chkValue) {
if (image == null) {
return;
}
if (chkValue) {
image.style.display = "inline";
} else {
image.style.display = "none";
}
}
// initialisation
setupCheckImageDisplay(imageSuppressAlerts, deviceSettings.isSuppressAlerts() );
setupCheckImageDisplay(imageOverrideTime, deviceSettings.isOverrideTime());
}
Its not the most elegant code in the world but it does get the job done