App: PaceMate

I'm very new to Monkey C programming and wanted to show off my latest app, PaceMate.

https://apps.garmin.com/apps/10f0ba71-cc76-4cfe-88b3-3f39825ff89f

My friends and I are used to speaking in km / h, but when we got into running it slowly changed into using pace (min / km) as a metric instead. We struggled to convert pace to km and had to take our phone out to find a website to convert it. Instead, I decided to create a Garmin app for it.

Features:

  1. Input pace, speed or goal time for a specific distance. The app will show the calculated values for the rest of the fields, based on the input.
  2. Define up to 4 custom distance fields in Connect IQ settings (apart from the default 5k, 10k, half marathon and marathon distances), and display these custom distance fields instead of the default distances.

My challenges in building this app:

  1. Finding a way to handle input (realising that Garmin API does not have a uniform way to capture pace, speed or time input).
    I ended up creating my own input views / delegate pairs to handle inputs for three different data types (pace, speed and time). They can now handle both touch (tap and flick) and button (press and hold) input.
  2. Supporting non-touch enabled devices.
    Still need to add a way for non-touch enabled devices to select fields and push a menu to allow users to select a different distance to display in that field.
  3. Clash with Hold DOWN hot key.
    In my app, when you want to use buttons for example to input pace, I made it so that if you HOLD the Up button, instead of just going up by 1 sec, the pace will go up by 5 (and increment significantly upon holding longer). The Down button works in the same way. However, if you have a hot key set for Hold DOWN, the hot key will take over and the onKeyReleased event will not be fired. Therefore, the input value will keep going down, until you press Down again and release it.

I still need to add support for the Imperial system, but I wanted to publish the app already.

What do you think?

Also if someone has a suggested solution for the "Clash with Hold DOWN hot key" issue, please let me know.

  • Haven't tried the app yet but I will say it's a great idea and it's something I was thinking of implementing myself.

    Also if someone has a suggested solution for the "Clash with Hold DOWN hot key" issue, please let me know.

    There's really nothing you can do about this in CIQ afaik. Some native views (like the map page, in pan/zoom mode) have the ability to override hot keys, but CIQ aps don't.

    We struggled to convert pace to km and had to take our phone out to find a website to convert it.

    If you use iOS, this is the best pace calculator app I've ever used:

    https://apps.apple.com/us/app/pacey-running-jogging-and-walking-pace-calculator/id932937393 

    It's simple, user-friendly and powerful. Pace, speed, distance and time are all on one screen, and the last values that were entered or calculated stick around, so you can quickly do several calculations in a row.

    It also lets you mix metric and imperial at will (any of the fields can be toggled to either system). And when you toggle units, the field value changes right away so it's easy to see that 5:00/km = 8:00/mile, or 20 kph is 12.4 mph, for example. 

    In general, whenever you change *any* value, the other fields change instantly, which is also makes it easier to do several calcs in a row.

    Just too bad it hasn't been updated in a few years. It still works great as long as you don't mind the fact that it doesn't go full-screen on modern phones.

    I find most of the other pace calc apps to be way too simple, but in a way that makes them more cumbersome and less useful. Like having a different screen for each field to calculate, only being able to set all fields to either metric or imperial, and not seeing results instantly, because the workflow to do a calc is basically filling out a form from scratch every time.

  • I will also say that after a certain point you probably won't use speed (km/h) at all for running, unless you run on a treadmill. (Ofc most treadmills force you to set your speed in kph or mph, even if they also display pace.)

    Once you get used to it, pace (min/km) is so much more convenient when it comes to doing certain calculations in your head or using your intuition to figure out how fast you're going.

    That's why I think pace calculators are really useful when they take any 2 of pace, distance and time as input, and spit out the 3rd metric as a result. Especially when you're able to mix and match imperial and metric at will - it's useful if you're reading an American website and you need to use a pace that's specified in imperial, but you want to calculate a distance in metric, for example.

    Being able to convert between pace and speed is kind of a bonus for me.

  • I tried your app on Forerunner 955 (5-button watch with touch) and here's my feedback:

    - The app seems completely unusable without touch, since there's no way to enter a value for any of the fields. However, it seems that the app supports a large number of devices without a touchscreen, which is probably not advisable, until the app can support button-only usage

    - There are also many devices where touch is optional - specifically, 5-button watches with a touchscreen like Forerunner 955 or Fenix 7. On these watches, it's usually expected that 99% of the system and app functionality should work even if touch is disabled in the system settings. For example, on my FR955, if touch is enabled, then the built-in keyboard defaults to a mode which requires touch, but if touch is disabled, it switches to a mode where buttons can be used. Contrast with watches like Venu and Vivoactive where touch is pretty much mandatory, since there are no buttons for scrolling - for these watches, touch cannot be disabled without also locking the buttons [which means that you pretty much can't use the watch UI at all in this state.]

    So I think that lack of button-only support is also an issue on 5-button "touch-optional" device, like Forerunner and Fenix.

    - If I edit pace, distance or time, and I long-press the DOWN button (and let go), the value start to decrease rapidly, then I'm taken to the music controls screen (which is default action for holding DOWN on FR955). When I return to your app, it acts like I held the DOWN button the whole time, and appears to have "queued up" a whole bunch of "decrease actions". Even when the value hits 0:00:00 (the minimum), these actions are still queued up no matter how long I wait - if I now press UP to increase the value, I can see the value decreasing by itself.

    Suggestions:

    - Remove support for hold DOWN and hold UP unless you can solve the problems with:

    -- the app thinking the user continued to hold the button except what really happened is the system took them to another screen

    -- the decrease actions being queued up, even when the value hits minimum. (I think that if the value hits min or max, then any queued actions should be discarded)

    [1/2]

  • - The way the UP and DOWN buttons work in general is very confusing. For pace, speed, and time, there are 2-3 spinners, but UP and DOWN only change the right-most spinner. Whenever any spinner "wraps" around, the value of the spinner to the left changes. I understand why this was done, but it's not typically how spinners work in other contexts.

    It's almost as if the intent was to combine the UX of a single spinner with the UX of multiple spinners, but I don't think this is intuitive in general.

    - The spinner controls [+/-] are too small and too close together for comfortable touch usage. The numbers and spinner controls should probably be larger (just to support easier touch usage)

    - There's no way to exit a data screen with touch, except for swipe right, which discards your changes. Ideally there would be ok (checkmark) and cancel (X) buttons for touch. Also, I would expect the START button hint to be tappable, just like it is for native screens.

    It also may not be super-intuitive that BACK / swipe right discards your changes. Might be nice:

    - to at least have a button hint (like X) for the BACK button, if not confirmation. (I can see how confirmation would be annoying)

    - to change the START button button hint to a checkmark

    - to have confirmation for the right swipe (or to disable right swipe and force the user to explicitly tap ok / cancel)

    Things I like:

    - All the values are "linked together" so changing any one of them instantly changes the others

    - Everything (except data entry) is on a single screen

    - Previous values are automatically persisted and restored when you reopen the app. (It is a bit jarring that the app always starts with default values, and the persisted values are loaded a split second later)

    I think the general idea is great, there's just a few usability issues that need to be worked on. I think it would help to look at how the native UI handles some of these things (spinners, selecting a field to edit). The Garmin UI isn't 100% perfect, but it's still helpful to see how they do certain things. If you have a 5-button watch with touch screen, take a look at how the Strength activity implements the reps/weight editing screen when you press LAP after a work interval.

    [2/2]

  • Summary of my feedback [with a few changes/additions from above]:

    - On app startup, if previous values are restored, display them initially, instead of displaying the default values first

    - Support button-only usage (it's crucial for non-touchscreen devices, and it's nice for "touch-optional" devices with 5 buttons)

    - Don't make app available for non-touch devices until button-only support is ready. People will install your app and be frustrated bc it's not usable at all

    - Change layout of distance fields so the distance increases from left-to-right, top-to-bottom.

    Before:

    5K HM

    10K M

    After:

    5K 10K

    HM M

    - Data entry screens

    - Make the spinners / numbers bigger to make touch usage more comfortable

    - Don't "link" the spinners. Make each spinner completely independent from the others, so that when one spinners wraps, the others are unchanged

    - Change the START button hint to green checkbox and make it tappable. (User needs a way to accept changes with touch)

    - Add red X as BACK button hint and make it tappable, so it's obvious that pressing this button discards changes

    - Remove right swipe support, as this discards changes and it's not obvious (the above point gives the user an obvious way to discard changes with touch)

    - Get rid of + / - buttons. These are redundant when you can swipe up or down to change the numbers. Instead, consider displaying arrows above and below the numbers to indicate that swipes are possible. Right now the existence of the +/- buttons seems to cause issues when you swipe up/down over a bigger distance and you accidentally hit the buttons. This causes the numbers to move in bigger steps than usual (e.g. +/-2, +/-3, or +/-4). In general I would expect the numbers to always smoothly move in 1-step increments, even if swiping further/faster causes the numbers to move faster (which I think they should)

    - Look at the Garmin quick timer / alarm UI and strength rep/weight editing screen for inspiration. (Yes I realize that the rep spinner has both swipes and +/-, but the difference is that when you swipe, it doesn't *also* trigger a +/- button.) I still think +/- is kind of redundant for this kind of thing, and Garmin doesn't use it in other places (not even the weight editing spinners)

    Nice-to-have features:

    - toggle between imperial and metric by tapping units on data entry screens

    - add field with user-defined distance

  • - add field with user-defined distance

    this does open up a can of worms, as once distance is editable, it raises the question of whether pace/speed or time should change in response to changes in distance.

    For example, if I initially set a pace of 5:00/km and a distance of 15 km, it's clear that the resulting time should be 5:00 * 15 = 1:15:00. But what happens if I subsequently set a distance of 20 km? Am I asking for a new time to be calculated or a new pace/speed? (This is probably why most simple pace calculators have a separate page for each field to be calculated, instead of putting everything on one page)

    Pacey, the ios app I mentioned above, solves this problem by asking you to "lock" one of metrics, but this may not be super intuitive, especially on an app that has to be simple enough to work on a watch

  • Awesome, thank you very much for your elaborate feedback!

    I will attempt to implement most points of your feedback over the next few days.

    As for the input points, I looked at the native input for time for an alarm. In that instance, you have to first select the hour part of the time and then the minutes part. I always found it annoying to have to confirm in between, which is why I made it possible to change them individually at any given time.

    Note, it is already possible to add a field with user-defined distance, although the distances need to be defined in the Connect IQ settings.

    You are correct that the swiping moves the numbers in bigger steps than usual. This is based on the distance of the swipe. I couldn't figure out how to update the view to show the numbers going up whilst swiping. Do you have any idea on that? Honestly I was expecting there to be native components for handling such types of inputs.

    I am considering adding a menu (button-enabled) as follows from the menu button on the main view:

    • Set pace
    • Set speed
    • Set {field 1} time
    • Set {field 2} time
    • Set {field 3} time
    • Set {field 4} time
    • Configure fields
      • Select field 1
      • Select field 2
      • Select field 3
      • Select field 4
    • Toggle metric/imperial --> Also updates the provided custom distances from meters to miles.
  • You are correct that the swiping moves the numbers in bigger steps than usual. This is based on the distance of the swipe. I couldn't figure out how to update the view to show the numbers going up whilst swiping. Do you have any idea on that? Honestly I was expecting there to be native components for handling such types of inputs.

    If I had to guess, I'd say you are handling swipes using onDrag() and not onSwipe(), since onSwipe provides no information about how far the user swiped.

    Seems to me that when the user drags by a certain fixed amount, you would change the spinner by 1 unit. If the user dragged by twice that amount, that should be interpreted as 2 drags. so you change the spinner by 1 unit, twice. This would allow spinner to change smoothly, like the native spinners, while still allowing the spinner to change faster if the user drags faster or for a longer distance.

    As for the input points, I looked at the native input for time for an alarm. In that instance, you have to first select the hour part of the time and then the minutes part. I always found it annoying to have to confirm in between, which is why I made it possible to change them individually at any given time.

    I agree that sucks - it makes sense for button-based editing but not touch-based editing. Maybe the way Garmin does things isn't so great after all haha (actually, I've felt this way many times)

  • I am considering adding a menu (button-enabled) as follows from the menu button on the main view:

    Another way you could implement this is as a cursor (or selection rectangle) that moves from field to field (using UP and DOWN). It would be more efficient than having a separate menu (although it might not be intuitive). Maybe the app could display a text hint about the UP and DOWN buttons on first startup. Might also help to put left and right arrow hints next to the buttons. Maybe this would be clear if the selection rectangle also had left and right arrows on it (or maybe not).

    I will say this is how selecting an activity data field to edit works (with the buttons), albeit without the selection rectangle or hints. Fwiw, some people complain about how this is unintuitive. I think adding a selection rectangle, button hints, and text hints could make it better, but I'm not sure. 

    For me, the appeal of an app like this is that you can do calculations fairly quickly, which is why I really like the "single page" design of Pacey (for example), as opposed to the other pace apps where every calculation (time, distance, pace, speed) is on a different page).

    Your app is closer to the single page design (although ofc the user input itself is on a separate page, out of necessity), which really appeals to me. If button users have to use a menu, I feel like it would be a lot tougher to use the app.

    In general, I do think it's tough to implement purely button-based interaction on Garmin devices. People have been complaining about unintuitive Garmin UI for a long time, and I think the main reason is that it's not intuitive to have to do everything with the buttons (or to have a touch-optional UI where everything *can* be done with the buttons).

  • Thank you so much for being so engaged!

    As for the onDrag/onSwipe, I actually was using onFlick. I looked into onDrag, but notice that a lot of devices do not support that. I will try to implement something similar using onFlick.

    I have just uploaded a new version in an attempt to support button-only devices. I now work with a cursor using selectables. I'm not yet happy with having to use the Menu button as a way to configure the fields now, but it's all I could do for now.

    My next project is improving the picker experience. You have given me quite some ideas for that!