避免
- 通过eclipse可以方便创建garmin项目, 但是要注意一点, app/face/widget/data模板都不一样, 中途切换会导致程序错误或者api权限不够, 想创建什么类型APP提前选择好类型
- 背景色不要设置成复杂的贴图纹理, 这样叠加图层时将渲染成非透明不混合方式以优化手表性能和耗电量
分类
当你用中文手表app的时候, 会列出来这几项, 下面进行一一对应和说明
(按键以forrunner235为例)
中文名 | 英文名 | 按键 | 权限 |
---|---|---|---|
应用程序 | application / app | 所有按键 | 权限完全开通, 无任何限制, 制作码表记录轨迹等需要长时间开启的应用, 在这里创建表盘会十分耗电切记 |
小工具 | widget | 确定/菜单/多层时支持返回/上/下 | 在手表默认表盘上下切换的临时应用/小工具, 它不支持动画, 大概30/60秒就自动回到默认表盘, 适合堆放临时信息, 比如心率/天气运动量统计/电量显示等 |
屏幕背景 | watchface | 无 | 默认界面, 表盘在初始化/甩手腕/从其他应用返回时提供秒钟刷新, 几秒后进入省电模式, 变为分钟刷新, 所以这里不适合做动画效果 |
数据字段 | data field | 无 | 为佳明运动app栏位显示, 佳明运动app支持将屏幕分割出多个区域, 数据位会显示在指定区域中, 功能和应用程序一样, 只是区域和按键有区别 |
代码相关
- 获取手表时间
var time = Sys.getClockTime();
time.sec time.min time.hour
用户设置的时间格式12/24
Gfx.System.getDeviceSettings().is24Hour
根据用户设置显示小时
var hourAuto = (!Gfx.System.getDeviceSettings().is24Hour&&time.hour>12)?time.hour%12:time.hour;
hourAuto.format("%02d")
- 获取日期
//Time.FORMAT_MEDIUM 为文字描述的长度
var date = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM);
var timeString = Lang.format("$1$-$2$ $3$", [date.month,date.day,date.day_of_week]);
- 系统屏幕类型
var isShapeRect = Sys.getDeviceSettings().screenShape == Sys.SCREEN_SHAPE_RECTANGLE;
- 系统颜色
COLOR_WHITE 白
COLOR_LT_GRAY 亮灰
COLOR_DK_GRAY 暗灰
COLOR_BLACK 黑
COLOR_RED 亮红
COLOR_DK_RED 暗红
COLOR_ORANGE 橙色/暗黄
COLOR_YELLOW 亮黄
COLOR_GREEN 亮绿
COLOR_DK_GREEN 暗绿
COLOR_BLUE 亮蓝
COLOR_DK_BLUE 暗蓝
COLOR_PINK 粉/亮紫
COLOR_PURPLE 暗紫
COLOR_TRANSPARENT 透明(尽量少用)
- 系统字体
只有相对大小的5种, 对应每块手表的相对大小, 如果你需要更大的字体, 则需要借助fnt扩展, 或者使用位图资源
1.0.x支持字体
FONT_XTINY 最小&纤细
FONT_TINY 最小号
FONT_SMALL 小号
FONT_MEDIUM 中号
FONT_LARGE 大号
FONT_NUMBER_MILD (只用于数字)
FONT_NUMBER_MEDIUM (只用于数字)
FONT_NUMBER_HOT (只用于数字)
FONT_NUMBER_THAI_HOT (只用于数字)
1.3.x支持字体
FONT_SYSTEM_XTINY 系统最小&纤细
FONT_SYSTEM_TINY 系统最小号
FONT_SYSTEM_SMALL 系统小号
FONT_SYSTEM_MEDIUM 系统中号
FONT_SYSTEM_LARGE 系统大号
FONT_SYSTEM_NUMBER_MILD 系统大号+(只用于数字)
FONT_SYSTEM_NUMBER_MEDIUM 系统大号++ (只用于数字)
FONT_SYSTEM_NUMBER_HOT 系统大号+++(只用于数字)
FONT_SYSTEM_NUMBER_THAI_HOT 系统大号++++ (只用于数字)
https://developer.garmin.com/downloads/connect-iq/monkey-c/doc/Toybox/Graphics.html
- 使用fnt字体 (fnt制作工具请自行搜索)
- 先将fnt文件拷贝到resources/drawables里面
- 然后修改描述文件drawables.xml, 将默认的drawables集合外面包含一层resources
- 把font加入进去
- 代码中调用此字体
<resources>
<drawables>
<bitmap id="LauncherIcon" filename="launcher_icon.png" />
</drawables>
<font id="fntTime1" filename="fntNum1.fnt" antialias="true"/>
</resources>
var fntTime1 = Ui.loadResource(Rez.Fonts.fntTime1);
- 创建文本
一共有三种方法,
- 默认模板会提供第一种, 也就是在resources/layouts下的xml配置文件里直接配置, 并通过onLayout加载进来
function onLayout(dc) {
setLayout(Rez.Layouts.WatchFace(dc));
}
- 创建有对象控制的文本函数
var txtUnit = new Ui.Text({
:text=>"",
:color=>Gfx.COLOR_WHITE,
:backgroundColor=>Gfx.COLOR_RED,
:font=>fntTime1,
:locX=>winW*.5f,
:locY=>i*winH*.2f,
:justification=>Gfx.TEXT_JUSTIFY_CENTER
});
//在onUpdate(dc)中绘制
txtUnit.draw(dc);
3.直接在onUpdate(dc)中绘制不带函数控制的渲染
dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_BLACK);
dc.drawText(100, 100 , fntTime1, i*10, Gfx.TEXT_JUSTIFY_CENTER);
不管哪一种都支持用fnt字体或系统内置字体
获取文本大小
getTextDimensions(text, font)
如何文本居中
实际上设置justification=>Gfx.TEXT_JUSTIFY_CENTER
可以令文本横向居中, 也就是locX位置为问题文本中心轴的位置, 而纵向呢, 纵向有两种方法设置居中
当你设置locY=>winSizeHeight*.5
并不是垂直居中, 你如何得到文本的高度呢, 非常简单
- 如果用上面第二种方法创建的文本, 并不能直接对对象进行获取txt.height, 因为没有进行draw(dc)渲染, 需要在onUpdate(dc)中进行了它draw(dc)后获取位置
- 第一种方法太麻烦了, 而且刷新时频繁计算又费事费电, 其实很简单, 系统给了api解决这一问题, 不需要渲染对象, 在创建之前就已经知道这个字体的高度了
var ftHHalf = Gfx.getFontHeight(Gfx.FONT_SYSTEM_NUMBER_HOT)*.5f;
- 隐藏属性, 发现还有更简单的设置方法....
设置justification为Gfx.TEXT_JUSTIFY_CENTER|Gfx.TEXT_JUSTIFY_VCENTER
- 如何使用数组
var pool = [];
加入对象
pool.add(obj);
获取大小
pool.size();
遍历
var len = pool.size();
for(var i=0;i<len;i++){
//do you want
}
- 如何设置计时器
var timer = new Timer.Timer();
timer.start(method(:requestUpdate), 10000, true);
停止/销毁计时器
if(timer!=null){
timer.stop();
timer = null;
}
计时器只工作在app(任何时候), widget(关闭之前), face (唤醒状态
function onExitSleep()
调用时) (休眠状态function onEnterSleep()
记得销毁和完成最后一次刷新表盘<比如秒针消除掉>)
face在休眠状态下调用timer会弹出警告, 提示权限不够, 不进行执行
- 枚举的创建和使用
MonkeyC既然从c语言简化而来, 自然也支持枚举
创建
enum{
TypeMode_Default,
TypeMode_Animation,
TypeMode_PowerSave
}
使用
switch(colorTemplete){
case TypeMode_PowerSave:
//do sth
break;
case TypeMode_Default:
default:
break;
}
强制Ui刷新
Ui.requestUpdate();
app通过animate或者timer可以达到每秒多次刷新
watchface可以在唤醒状态使用timer刷新如何输出, 错误
- 输出log
Sys.println(str);
- 弹出错误
Sys.error(str);
- 如何使用数学函数Math
using Toybox.Math;
- 获取随机数
function rand(num){
Math.srand(Math.rand());
return Math.rand()%num;
}
- 获取随机0~1小数
function ran(){
Math.srand(Math.rand());
return Math.rand()%10000/10000.0f;
}
- 绘制图形
在Toybox::Graphics::Dc
下
- clear 用背景色填充屏幕
- clearClip 重置dc整个区域 (2.3)
- drawArc(x, y, r, attr, degreeStart, degreeEnd) 画弧
- drawBitmap(x, y, rez) 将资源贴图绘制上来
- drawCircle(x, y, radius) 画圈
- drawEllipse(x, y, a, b) 画椭圆圈
- drawLine(x1, y1, x2, y2) 画线
- drawPoint(x, y) 画点
- drawRectangle(x, y, width, height) 画矩形框
- drawRoundedRectangle(x, y, width, height, radius) 画圆角矩形框
- drawText(x, y, font, text, justification) 绘制文本
- fillCircle(x, y, radius) 画圆
- fillEllipse(x, y, a, b) 画椭圆
- fillPolygon(pts) 画多边形
- fillRectangle(x, y, width, height) 画矩形
- fillRoundedRectangle(x, y, width, height, radius) 画圆角矩形
- setClip(x, y, width, height) 设置dc的绘制区域
- setColor(foreground, background) 设置前景色和背景色, 通过创建对象后刷新不会因为setColor而改变, 需要通过自己的函数setColor以及setBackgroundColor进行改变
- setPenWidth(width) 设置线宽度
- view的运行次序
插件和应用
onLayout() → onShow() → onUpdate() → onHide()
表盘
onLayout() → onShow() → onUpdate()
数据栏
onLayout() → onShow() → onUpdate()
这些都是任何语言都具备的功能, 然后下一篇如果经验积累够了会讲手表感应器api(心率,gps等), 或者手表自带组件(个人感觉没太大兴趣)