supporting both physical button and touch input

I find it very hard to support "correct"/user friendly input for an app across different devices.

On example:

I made it work with behaviordelegate. As an example let's look at onSelect. Works fine on devices with physical select button.

But/and It also "works" on devices without select button. For example on edge devices (ee2) a touch of the screen generates onSelect. This could be OK, though I don't like it.

And on watches ie: fr965 that both are touch screen and have a physical select button it kind of works: either I click the button or when I touch the screen anywhere an onSelect event is generated.

However I'd like to be more user friendly and be able to know where the screen was tapped, and react accordingly. This could be achieved by disabling the onSelect (for example by removing the onSelect method using an annotation) and thus onTap will be called when the screen is touched, which is good, but when a user clicks the physical button then nothing happens.

Ideally I would hope that I could disable the translation of taps to onSelect from the code. Or onTap should be called before onSelect. But to my knowledge none of this is possible. Are they?

So the only way I can think of supporting "both" touch and physical buttons is by adding a stupid, unnecessary user setting where they can disable the physical buttons. When they chose this setting then onSelect would return false => onTap will be called.

Does anyone have a good solution for this?

  • Lock is different.  With that, buttons are also disabled except for the unlock method.

    You're right, my mistake. Too bad the Garmin manuals don't really clarify that, but I tried it with a VA3 (and it's as you said), plus many people complained on the internet about being unable to lock the touchscreen without also locking the buttons, on VA watches.

    That might answer the question of why flocsy would want a way to disable touch from within his app which is separate from natively locking touch - so the user can continue to use buttons, even on something like a VA5 or Venu 3.

    I still don't understand flocsy's definition/criteria for "mandatory touch" (as a watch that doesn't have physical buttons for all of the back, select and menu functions).

    If the issue is giving the user a way to re-enable touch, I can think of ways that could be done on a watch with even one button (VA3). e.g. Just let the user long-press or swipe the screen to re-enable touch.

    And just because the user has physical buttons for back, select and menu, doesn't mean it would be convenient for them to use some sort of app menu to re-enable touch (if that was the intent), since they'd still be unable to scroll with touch disabled on a VA5 (for example).

  • I'm pretty sure you're a relative of Leo Tolstoy :) 

    Anyway. My app is a hiking app. One of the users told me that when he hikes the sleeves of his shirt sometimes touches the screen and that stops the hike. 

    So the goal is to make it possible to disable touch (or maybe even only "part of" touch) in my app. Not requiring to disable touch or lock the whole watch. And also the goal is not to disable touch for everything but keep a way to re-enable it. The goal is to disable those parts that might be annoying, but let the user use most of the app/watch as usually.

    That's also why my definition of "mandatory" means that if the watch can't do some of the functionality it has to do to use my app without touch (i.e the only way to trigger onSelect is via touch, there's no way to do it with a physical button) the I can't disable touch, because the user won't be able to start and stop the activity.

  • So the goal is to make it possible to disable touch (or maybe even only "part of" touch) in my app. Not requiring to disable touch or lock the whole watch.
    And also the goal is not to disable touch for everything but keep a way to re-enable it

    Yeah, that's what I eventually gathered, thank you for confirming that.

    That's also why my definition of "mandatory" means that if the watch can't do some of the functionality it has to do to use my app without touch (i.e the only way to trigger onSelect is via touch, there's no way to do it with a physical button) the I can't disable touch, because the user won't be able to start and stop the activity.

    Well, onSelect is actually not synonymous with starting and stopping an activity, as noted in the other thread. It just so happens that on 5-button watches, the button that triggers onSelect also starts/stops an activity. onSelect on the "touch-first watches" (like Vivoactive and Venu) is actually a tap of the touchscreen, and NOT a button press. On the other hand, if I'm not mistaken, on every watch, including VA3 (which only has 1 button), starting and stopping a native activity is accomplished with a short press of a button.

    So:

    - by your original definition/criteria of mandatory touch (has physical buttons for back, menu, select), only VA3 series is "mandatory touch"

    - if the criteria for "mandatory touch" is "can't start/stop activity with button" and/or "touch is used to start/stop activity", no devices fit that bill

    I think that you can allow your app to disable touch for all devices. All you need to do is have a way to re-enable touch, which would could be a long-press or swipe of the touchscreen, and to use a button to start/stop the activity.

    So if I were implementing this:

    - KEY_ENTER would start/stop the activity (just like on all native devices, including both "touch-first" / VA+Venu and "touch-optional" / Forerunner devices)

    - Tapping on the screen would *not* start/stop an activity (unless you want this to be an option, which I would disable by default). (Then again, if this is what you and your users want, I can't argue with that.)

    - There would be a menu item to disable touch (or maybe an icon on the activity screens that could be long pressed?). Tbh I could go either way, depending on how the activity screens are designed. Maybe you could even use long press + swipe to disable the touchscreen?

    - To re-enable touch, you could use long-press or swipe of the screen, or perhaps long-press + swipe. Long-press of a button could be an option for some devices (not VA3 for sure), but ofc system hot keys could interfere with that, as discussed elsewhere

    However, if the only (or main) reason for disabling touch in the app is to avoid accidental start/stop, then:

    - if tap to start/stop is no longer implemented, then maybe you don't need to have an option to completely disable touch

    - if tap to start/stop becomes an option, then maybe you don't need to also have an option to completely disable touch

  • Anyway. My app is a hiking app. One of the users told me that when he hikes the sleeves of his shirt sometimes touches the screen and that stops the hike. 

    And that was why when I got my first 5 button watch with touch, I used the system setting to turn off touch when I was using my hiking app with sleeves.

    There wasn't a similar option for two button devices, so I was just very careful or I'd wear it over the sleeve.  Wearing a watch over the sleeve may be an option, but based on the material, may cause issues with OHR, in which case, use an external monitor

    For my hiking app, a brush with a sleeve may change screens, but doesn't start/stop the activity.  I use onKey for that so a button is needed.

  • Anyway. My app is a hiking app. One of the users told me that when he hikes the sleeves of his shirt sometimes touches the screen and that stops the hike. 

    Yeah the solution here (imo) is to be just like the native activities and jim_m_58's hiking app: use KEY_ENTER to start/stop the activity, not a tap of the screen.

    I'm almost 100% sure there's no device where a tap of the screen will start/stop the activity timer.

    And accidental touches have always been a complaint, for every single Garmin touchscreen device. The main issue was accidentally saving an activity while it was paused, due to rain or a long sleeve.

    (The current 5-button touchscreen devices, like Forerunner 265/955/965 and Fenix 7, have had different ways of addressing this. First they always disabled touch in the activity pause menu, regardless of touch settings, but most people hated that. Now they ask for confirmation for both save and discard if you trigger those functions via touch. If you trigger those functions via buttons, only discard comes with a confirmation prompt.)

  • Speaking of behaviours, it is interesting that BehaviorDelegate has an onSelect() method but no onTimerStartStop(), which might be what leads to the confusion that "select" is the same as "timer start/stop".

    This seems like an oversight tbh. But then again, maybe onTimerStartStop wouldn't be the best name for that behaviour. Not sure what would be, which is maybe why it was omitted.

  • that imaginary behavior should not have timer in it's name IMHO. startStop is ok, you can start a game, an app, etc.But timer is only relevant for activities.

  • Good point. Kinda moot since it won't be implemented.

    Indeed, if you have a device app on a "touch-first" device (venu or va) which wants to detect the key that normally starts/stop native activities (KEY_ENTER / top-right button / only button on VA3), you can't use a BehaviorDelegate for that, you have to use an InputDelegate. (EDIT: you can't use BehaviorDelegate-specific methods)

    Perhaps BehaviorDelegate was never meant to cover all useful inputs, idk. Or maybe it was made with non-touch devices in mind. (Shortly after CIQ was initially released, the OG Vivoactive came out. DeviceSettings.isTouchScreen was only added in CIQ 1.2.0 tho.)

  • you can't use a BehaviorDelegate for that, you have to use an InputDelegate.

    Nope..  I've used a BehaviorDelegate with onKey() and onBack() (as examples) for years, including on a va3!.

    "class HikeDelegate extends Ui.BehaviorDelegate {"

  • Sorry, I should've said you can't use the methods specific to BehaviorDelegate for that. Ofc you can use BehaviorDelegate itself, as it inherits from InputDelegate. I was specifically referring to the practice of assuming that onSelect is the same as activity start/stop, which seems to come from the mindset of wanting the app to (only) react to behaviors instead of key presses.

    Very poor choice of words.