Help with Bitmap Watchface + Digital Display (or Analog Display)

Hi!

I am trying to create a simple watch face. A simple picture plus showing the time. I would prefer analog, but having a digital format as well will be ideal for diversity.

The bitmap seems to be an issue when I try to run the app.

This is the notification it provides:

Error: Unexpected Type Error

Details: Failed invoking <symbol>

Stack: 

  - onUpdate() at /Users/ramirezla/eclipse-workspace/RUTA/source/RUTAView.mc:51 0x10000191 

Can someone help shed some light on this?

The View.mc file: 

using Toybox.WatchUi;

using Toybox.Graphics;

using Toybox.System;

using Toybox.Lang;

using Toybox.Application;

class TestView extends WatchUi.WatchFace {

    var bitmap;

    function initialize() {

        WatchFace.initialize();

    }

    // Load your resources here

    function onLayout(dc) {

        bitmap = WatchUi.loadResource(Rez.Drawables.TestView);

    }

    // Called when this View is brought to the foreground. Restore

    // the state of this View and prepare it to be shown. This includes

    // loading resources into memory.

    function onShow() {

    }

    // Update the view

    function onUpdate(dc) {

        // Get the current time and format it correctly

        

        dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_BLACK);

        dc.clear();

        dc.drawBitmap(50, 50, bitmap);

        

        var timeFormat = "$1$:$2$";

        var clockTime = System.getClockTime();

        var hours = clockTime.hour;

        if (!System.getDeviceSettings().is24Hour) {

            if (hours > 12) {

                hours = hours - 12;

            }

        } else {

            if (Application.getApp().getProperty("UseMilitaryFormat")) {

                timeFormat = "$1$$2$";

                hours = hours.format("%02d");

            }

        }

        var timeString = Lang.format(timeFormat, [hours, clockTime.min.format("%02d")]);

        // Update the view

        var view = View.findDrawableById("TimeLavel");

        view.setColor(Application.getApp().getProperty("ForegroundColor"));

        view.setText(timeString);

        // Call the parent onUpdate function to redraw the layout

        View.onUpdate(dc);

    }

    // Called when this View is removed from the screen. Save the

    // state of this View here. This includes freeing resources from

    // memory.

    function onHide() {

    }

    // The user has just looked at their watch. Timers and animations may be started here.

    function onExitSleep() {

    }

    // Terminate any active timers and prepare for slow updates.

    function onEnterSleep() {

    }

}

  • Ok. here's a simple sample where "view" is never used.  Everything is using direct dc calls.

    using Toybox.WatchUi;
    using Toybox.Graphics;
    using Toybox.System;
    using Toybox.Lang;
    
    class bgbmpView extends WatchUi.WatchFace {
    	var width, height;
    	var bitmap;
    	
        function initialize() {
            WatchFace.initialize();
            bitmap=WatchUi.loadResource(Rez.Drawables.bg);
        }
    
        function onLayout(dc) {
            width=dc.getWidth();
            height=dc.getHeight();
        }
    
        function onShow() {
        }
    
        // Update the view
        function onUpdate(dc) {
            // Get and show the current time
            var clockTime = System.getClockTime();
            var timeString = Lang.format("$1$:$2$", [clockTime.hour, clockTime.min.format("%02d")]);
    		
    		dc.setColor(Graphics.COLOR_BLACK,Graphics.COLOR_BLACK);
    		dc.clear();
    		
    		dc.drawBitmap(0, 0, bitmap);
    		
    		dc.setColor(Graphics.COLOR_BLUE,Graphics.COLOR_TRANSPARENT);
    		dc.drawText(width/2,height/2,Graphics.FONT_NUMBER_HOT,timeString,Graphics.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER);
        }
    
        function onHide() {
        }
    
        // The user has just looked at their watch. Timers and animations may be started here.
        function onExitSleep() {
        }
    
        // Terminate any active timers and prepare for slow updates.
        function onEnterSleep() {
        }
    
    }

    And the result:

  • And the same using a layout:

    using Toybox.WatchUi;
    using Toybox.Graphics;
    using Toybox.System;
    using Toybox.Lang;

    class bgbmp2View extends WatchUi.WatchFace {

    function initialize() {
    WatchFace.initialize();
    }

    // Load your resources here
    function onLayout(dc) {
    setLayout(Rez.Layouts.WatchFace(dc));
    }

    function onShow() {
    }

    // Update the view
    function onUpdate(dc) {
    // Get and show the current time
    var clockTime = System.getClockTime();
    var timeString = Lang.format("$1$:$2$", [clockTime.hour, clockTime.min.format("%02d")]);
    var view = View.findDrawableById("TimeLabel");
    view.setText(timeString);

    // Call the parent onUpdate function to redraw the layout
    View.onUpdate(dc);
    }

    function onHide() {
    }

    // The user has just looked at their watch. Timers and animations may be started here.
    function onExitSleep() {
    }

    // Terminate any active timers and prepare for slow updates.
    function onEnterSleep() {
    }

    }

    and this for the layout:

    <layout id="WatchFace">
    <bitmap id="bg" x="0" y="0" filename="../drawables/hiker2.png" />
    <label id="TimeLabel" x="center" y="center" font="Graphics.FONT_NUMBER_HOT" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_BLUE" />
    </layout>

  • Notice in the second example, the only change from the watchface template is adding the bitmap to the layout.  I changed the font for the time, just so they would look the same as the dc example.

    BTW, the layout version takes .8k more memory than the dc version if you're worried about memory. (layout version is 63.3k, but most of that is the bitmap)

  • THANK YOU THANK YOU THANK YOU

    Your direct dc calls worked marvelous. I have attached a picture of how it came out. My next goal is to figure out how to code an analog watch.  

    I cannot stress enough how thankful I am for your help

    .

  • Follow-up questions.

    1. Is there a way to keep my image on the same location for several watches? At the moment, it bounces around.

    2. Is there a way to offer different color fonts to the time or backgrounds without creating multiple apps for the user to download?

  • 1. I don't understand what you are asking.

    2.  for the fonts, you can use app settings or on device settings to vary the color.  For bitmaps you need a different one if you want different colors.

  • 1. At the moment, the png on the fēnix is directly on the 12 o'clock. If a user would select the Forerunner 945 it shifts away from the 12 o'clock. Same goes for any other watch a user would have.

    2. so it seems a user would be able to change the font color on their own, correct if it was not a bitmap. But considering I am using a bitmap, I'd need to upload new watch faces, correct?

  • 1. Which fenix?  Some are 240x240, and others 260x260 or 280x280.

    if you hard code the location of the drawBitmap, it will shift.

    you need to use the width of the display to position it correctly, and can also use the width of the bitmap.

  • I limited the selection since I believe it is hard coded. It's best to prob use the width of the bitmap. I prefer to have more options available.

  • The 6x is 240x240 while the f6x is 280x280

    See my dc example, and using width,

    width/2 is the middle of the screen

    and

    bwWidth=bitmap.getWidth()

    will give you the width of the bitmap.

    so, if you draw the bitmap using

    x=width/2-bmWidth/2

    you get the "x" to center the bitmap.