Usability of the layout system

The layout system is there to abstract differences between devices, but it isn't sufficient to make it easy, or I'm missing something.

Assume for a second that I have a drawable that displays a battery status. Assume also that I want to be able to control the positioning of that battery status indicator via the layout file. As it currently stands, I can create a layout with text/bitmaps/circles/boxes/points/lines. If I want to place my battery indicator, I have to create a label that represents the position of the indicator and use that...

function onLayout(dc) {
var layout = Ui.loadResource(Rez.Layouts.TestLayout);

// the 4th layout element is a label that acts as a position indicator for
// the battery status indicator. replace that label with the battery status.

layout[3] = new BatteryIndicator({
:locX => layout[3].locX,
:locY => layout[3].locY - 17, // hack because fonts are specified by bottom edge instead of top like everything else
:width => 28,
:height => 20
});

setLayout(layout);
}


This is a frustrating hack to have to make because some of the position/size code for my indicator is still stuck in the application code, and some of it is stuck in the layout specification. It would be nice if I could somehow register my drawable classes with the factory that builds up the layouts from the xml data. That way I could specify the layout of my application screens fully inside the layout file...

<layout id="TestLayout" background="Gfx.COLOR_WHITE">
<label x="8" y="8" font="Gfx.FONT_LARGE" text="" justification="Gfx.TEXT_JUSTIFY_LEFT" color="Gfx.COLOR_WHITE" />
<label x="8" y="44" font="Gfx.FONT_LARGE" text="" justification="Gfx.TEXT_JUSTIFY_LEFT" color="Gfx.COLOR_WHITE" />
<label x="8" y="80" font="Gfx.FONT_LARGE" text="" justification="Gfx.TEXT_JUSTIFY_LEFT" color="Gfx.COLOR_WHITE" />
<batteryIndicator x="2" y="2" width="28" height="20" bgcolor="Gfx.COLOR_WHITE" />
<moveBar x="0" y="140" width="205" height="8" bgcolor="Gfx.COLOR_WHITE" />
</layout>


In order for something like this to work, I'd have to register a function to create my object given a name and a dictionary of attributes. Something like this would be ideal.

class BatteryIndicator
{
hidden var locX;
hidden var locY;
hidden var width;
hidden var height;
hidden var color;

function initialize(params) {
locX = params.get(:locX);
locY = params.get(:locY);
width = params.get(:width);
height = params.get(:height);
color = params.get(:color);
}

function draw(dc) {
// snipped...
}

// snipped...
}

class TestApp extends App.AppBase {

function onStart(state) {
Ui.registerType("batteryIndicator", BatteryIndicator);
Ui.registerType("moveBar", MoveBar);
}

function onStop(state) {
Ui.deregisterType("moveBar");
Ui.deregisterType("batteryIndicator");
}
}


I'm not exactly sure how the machinery would work, but it would be very helpful to have this. It seems a large part of the system is in place already, so maybe this is the direction you are already headed.
  • Former Member
    Former Member over 10 years ago
    Jumping in the discussion here with question related to layouts (the search functionality on this forum is a nightmare): is there a way to figure if an app/widget is running on a square or round device in roder to switch between layouts defined in resources/xml?
  • The layout system is designed so it's not necessary for your to try to determine what device the app is running on. While there isn't currently a way to designate a layout for a class of devices (e.g. all square screens or all round screens), you can set layouts per device.

    For example, in addition to the 'resources' folder, which is the default resources location, you can create a 'resources-epix', 'resources-fenix3', 'resources-vivoactive', etc., which will contain resources specific to its respective platform.

    Since all of the square-type devices are very similar, you may be able to get away with leaving the square layout in the default 'resources' folder, and then create 'resources-fenix' and 'resources-d2bravo' folders for the two round devices (these would essentially contain the same layout information), but it will depend on the requirements of your app.
  • Former Member
    Former Member over 10 years ago
    The layout system is designed so it's not necessary for your to try to determine what device the app is running on. While there isn't currently a way to designate a layout for a class of devices (e.g. all square screens or all round screens), you can set layouts per device.

    For example, in addition to the 'resources' folder, which is the default resources location, you can create a 'resources-epix', 'resources-fenix3', 'resources-vivoactive', etc., which will contain resources specific to its respective platform.

    Since all of the square-type devices are very similar, you may be able to get away with leaving the square layout in the default 'resources' folder, and then create 'resources-fenix' and 'resources-d2bravo' folders for the two round devices (these would essentially contain the same layout information), but it will depend on the requirements of your app.


    Thanks for the answer, I'll go for a default layout for square watches and specifics for the round ones. Why I'm asking is because (at least in the simulator), placing a label at dc.getHeight()/2 (so basically centering it) doesn't actually position the label in the middle of the screen, neither its positions it at the same location on all round watches.
  • The layout system is designed so it's not necessary for your to try to determine what device the app is running on. While there isn't currently a way to designate a layout for a class of devices (e.g. all square screens or all round screens), you can set layouts per device.

    For example, in addition to the 'resources' folder, which is the default resources location, you can create a 'resources-epix', 'resources-fenix3', 'resources-vivoactive', etc., which will contain resources specific to its respective platform.

    Since all of the square-type devices are very similar, you may be able to get away with leaving the square layout in the default 'resources' folder, and then create 'resources-fenix' and 'resources-d2bravo' folders for the two round devices (these would essentially contain the same layout information), but it will depend on the requirements of your app.


    I actually ran into some difficult issues myself over the weekend where I also had to revert to checking if a watch has round or square face.

    Here is the post where I found the solution:
    https://forums.garmin.com/showthread.php?228721-In-App-Device-Detection