How to get a reference to a <button> element from a View?

I'm building a widget and trying to manipulate a <button> element (which is created with an xml layout) from the View but I can't figure out how to get a reference to it before it's selected (I know I can get a reference to it from the behavior handler after its selected, but I want to set its state on init based on an api response). I can't add an id attribute to it since that doesn't seem to be supported so I can't use View.findDrawableById(), which I've used for other layout elements. Is there some other way to get a reference to it?

  • Can you implement a custom button class, pass in the ID as a custom param in the XML, and set the selectable identifier in the constructor?

  • Not sure how that would work in the xml -- tried a few variations along those lines without success (too many arguments error:

    class CustomButton extends Ui.Button {
        etc.
    }
    
    ---
    
    <button x="20" y="130" width="111" height="111" behavior="onButton" class="CustomButton">
        <state id="stateDefault" bitmap="@Drawables.DefaultButton" />
    </button>

  • I was able to get it to work, but I don't think you need to use this approach since adding id in the XML does work after all. Here's a proof-of-concept anyway. I modified the SDK Selectable sample and tested in the sim with SDK 6.3.0.

    button_layout.xml

    (added button id and class)

    <layout id="ButtonLayout">
        <button x="40" y="center" width="50" height="50" background="Graphics.COLOR_BLACK" behavior="onBack"
          class="CustomButton" id="adfasd">
            <state id="stateDefault" bitmap="@Drawables.DefaultBackButton" />
            <state id="stateHighlighted" bitmap="@Drawables.PressedBackButton" />
            <state id="stateSelected" bitmap="@Drawables.PressedBackButton" />
            <state id="stateDisabled" color="Graphics.COLOR_BLACK" />
        </button>
        <button x="115" y="center" width="50" height="50">
            <state id="stateDefault" bitmap="@Drawables.DefaultMenuButton" />
            <state id="stateHighlighted" bitmap="@Drawables.PressedMenuButton" />
            <state id="stateSelected" bitmap="@Drawables.PressedMenuButton" />
            <state id="stateDisabled" color="Graphics.COLOR_BLACK" />
            <param name="background">Graphics.COLOR_BLACK</param>
            <param name="behavior">onMenu</param>
        </button>
    </layout>

    ButtonView.mc

    (added CustomButton class)

    class CustomButton extends WatchUi.Button {
        function initialize(settings as {
            :behavior as Lang.Symbol,
            :background as Graphics.ColorType or WatchUi.Drawable,
            :locX as Lang.Numeric,
            :locY as Lang.Numeric,
            :width as Lang.Numeric,
            :height as Lang.Numeric,
            :stateDefault as Graphics.ColorType or WatchUi.Drawable,
            :stateHighlighted as Graphics.ColorType or WatchUi.Drawable,
            :stateSelected as Graphics.ColorType or WatchUi.Drawable,
            :stateDisabled as Graphics.ColorType or WatchUi.Drawable,
            :identifier as Lang.Object,
            :visible as Lang.Boolean
        }) {
            System.println("settings.identifier = " + settings[:identifier]);
            WatchUi.Button.initialize(settings);
        }
    }
    

  • Thanks I was able to get it working with that sample code as reference.

    However, when I only add an id to the non-custom button element xml (e.g. <button id="adfasd">), it doesn't work for me in sim on 6.3.0 sdk -- I get this error:

    ERROR: edge1030plus: ...path\source\Rez.mcgen:40,12: Undefined symbol ':adfasd' detected.
    ERROR: edge1030plus: ...path\source\Rez.mcgen:40,12: No class found for new object instantiation.

    What makes you say you adding id in the XML does work after all? Were you able to run it that way somehow or are you seeing some docs implying that?

  • Interesting, I didn't try it without the class attribute. You're right, it doesn't work that way. I think it's a bug in the compiler tbh.

    The documentation for the selectable xml says that id is an attribute, and it says that button expands on the definition of selectable. To me that means id should be supported for button (and it obviously is, as long as you also supply class.)

    https://developer.garmin.com/connect-iq/core-topics/input-handling/

  • OK yeah i saw that same thing in the docs and assumed button should support it -- thanks for confirming! I'll just use the custom instance workaround for now.

  • BTW, I found an even easier workaround: set class equal to "WatchUi.Button" and you don't have to implement a custom button class.

    e.g.

    <button id="wow" class="WatchUi.Button" x="175" y="center" width="50" height="50" />