Garmin ConnectIQ app with a list / menu as the first view

1.2k views Asked by At

How can I set up the first view of my watch app to be a menu, or similar scrolling list?

I see this behaviour all the time on Fenix 5; for example, in the Navigate app (press "select", choose "Navigate"), the first screen is a scrolling list of options. I want the same thing in my app, with the list being created and controlled programmatically.

However returning a menu from getInitialView() gives me "Unexpected Type Error".

Just to clarify: I don't really care if it's actually a menu. But I want to be able to see multiple items in the list at once, and if the list is larger than the screen, have the up and down buttons scroll it. Having the items be custom views that I can draw programmatically would be a big plus.

I guess I could manually draw the list, and manually implement smooth scrolling; but that's way too tedious. I have to believe that there's a built-in facility for this, since I see this exact thing happen consistently in so many places.

(Please note I'm asking about a watch app -- i.e. something you get to by pressing "select" (top-right) and choosing it from the list. Not a widget, watch face, or data field.)

(Edited to clarify watch app, and use Navigate as an example.)

1

There are 1 answers

3
douglasr On

Unfortunately, you cannot set up the first view of your app (regardless of the app type) to be a menu. The CIQ framework expects that a call to the getInitialView() function will return an array with the first element an object of type View. If you use the built in support for menus, you will receive an error.

Instead, you will have to create your own "view" which renders a menu (that you display manually) and then handle the up/down input manually with your own InputDelegate object.

It should be noted that creating your own menu system will only work with a watch-app. With watch faces and data fields there is no ability to handle any input events, and with widgets your InputDelegate object will not receive any UP or DOWN events until you have replaced your initial view with a second view. When you have rendered a second view on a widget, typically after the user presses the start button, your InputDelegate object will receive all events.

Another option would be to render the app title and/or typical information on the initial view and set a timer to push a new view (which would be your menu) a second or so after the initial screen is rendered. This option would enable you to use the built in menu functionality and thus reduce code complexity, which is especially nice if you plan to support multiple devices with varying size and styles.

I haven't run the code but something like this for your initial view should work:

class SomeView extends Ui.View {

    var startupTimer;
    var isFirstTime = true;

    function initialize(ident,page) {
        startupTime = new Timer.Timer();
    }

    function onShow() {
        if (isFirstTime) {
            isFirstTime = false;
            startupTimer.start( method(:startupTimerCallback), 1000,  false );
        }
    }

    function onUpdate(dc) {
        if (isFirstTime) {
            // render the startup view (title, version, etc) here...
        }
    }


    function startupTimerCallback() {
        Ui.pushView(new Rez.Menus.MainMenu(), new MainMenuInputDelegate(), Ui.SLIDE_LEFT);
    }

}