読者です 読者をやめる 読者になる 読者になる

Pebbleアプリ開発メモ

Pebbleアプリ、Watchface開発のメモを残していきます。

【Pebble】公式アラームアプリのようなUIを作成する

Pebble

f:id:shotsep:20151001165635p:plain

以前に紹介したCurrency Converter。海外から買い物をする機会が多いので重宝してます。

そもそも作ろうと思ったきっかけは、ストアにいいUIのコンバーターがなかったからでした。

Currency ConverterのUI

f:id:shotsep:20150929110345g:plain

公式のアラームアプリのような、中心のボタンで桁を選択、上ボタン/下ボタンで加算/減算をするUIです。

ご存知の通りPebbleにはタッチスクリーンが搭載されていないので、UIは他のデバイスと違う方法でアプローチしないといけません。

調べていたところ、Number Windowというクラスを使うと実現できそうだったのですが、どうも1桁しかおけないようなので自作しました。

NumberWindow不使用で実現
#include <pebble.h>

#define NUMBER_COUNT 2
  
static void up_click_handler(ClickRecognizerRef recognizer, void *context);
static void select_click_handler(ClickRecognizerRef recognizer, void *context);
static void down_click_handler(ClickRecognizerRef recognizer, void *context);
static void click_config_provider(void *context);

Window *window;

TextLayer *numBox[NUMBER_COUNT];
char c[NUMBER_COUNT][4];
uint8_t boxIndex = 0;

TextLayer *ampmBox;
char ampmChar[8];
uint8_t ampmIndex = 0;

char currencyNameArray[2][6] = {"AM",
                                 "PM",
                                };

void window_load(Window *window) {
  
  for (int i = 0; i < NUMBER_COUNT; i++) {
    numBox[i] = text_layer_create(GRect(29 + (i * 48), 40 , 40, 35));
    text_layer_set_font(numBox[i], fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
    text_layer_set_text_alignment(numBox[i] , GTextAlignmentCenter);
    snprintf(c[i], sizeof(c[i]), "%02d", 0);
    text_layer_set_text(numBox[i], c[i]);
    layer_add_child(window_get_root_layer(window), text_layer_get_layer(numBox[i]));
  }
  
  text_layer_set_background_color(numBox[boxIndex], GColorBlack);
  text_layer_set_text_color(numBox[boxIndex], GColorWhite);
  
  ampmBox = text_layer_create(GRect(47, 87, 50, 30));
  text_layer_set_font(ampmBox, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD));
  text_layer_set_text_alignment(ampmBox , GTextAlignmentCenter);
  snprintf(ampmChar, sizeof(ampmChar), "%s", currencyNameArray[0]);
  text_layer_set_text(ampmBox, ampmChar);
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(ampmBox));
}

void window_unload(Window *window) {

}

void init(void) {
  window = window_create();
  window_set_background_color(window, GColorWhite);
  window_set_window_handlers(window, (WindowHandlers) {
      .load = window_load,
      .unload = window_unload
      });

  window_stack_push(window, true);
  
  window_set_click_config_provider(window, click_config_provider);
}

void deinit(void) {
  window_destroy(window);
}

int main(void) {
  init();
  app_event_loop();
  deinit();
}

static void click_config_provider(void *context) {
  window_single_click_subscribe(BUTTON_ID_UP, up_click_handler);
  window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);
  window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler);
}

static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
  
  boxIndex++;
  
  if(boxIndex < 2) {
    for (int i = 0; i < NUMBER_COUNT; i++) {
      text_layer_set_background_color(numBox[i], GColorClear);
      text_layer_set_text_color(numBox[i], GColorBlack);
    }

    text_layer_set_background_color(numBox[boxIndex], GColorBlack);
    text_layer_set_text_color(numBox[boxIndex], GColorWhite);
  }
  else if(boxIndex == 2) {
    
    for (int i = 0; i < NUMBER_COUNT; i++) {
      text_layer_set_background_color(numBox[i], GColorClear);
      text_layer_set_text_color(numBox[i], GColorBlack);
    }
    
    text_layer_set_background_color(ampmBox, GColorBlack);
    text_layer_set_text_color(ampmBox, GColorWhite);
  }
  else {
    boxIndex = 0;
    
    text_layer_set_background_color(numBox[boxIndex], GColorBlack);
    text_layer_set_text_color(numBox[boxIndex], GColorWhite);
    
    text_layer_set_background_color(ampmBox, GColorClear);
    text_layer_set_text_color(ampmBox, GColorBlack);
  }
}

static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
  if(boxIndex < 2) {
    int current = atoi(text_layer_get_text(numBox[boxIndex]));
    current = (current < 12) ? current + 1 : 0; 
    snprintf(c[boxIndex], sizeof(c[boxIndex]), "%02d", current);
    text_layer_set_text(numBox[boxIndex], c[boxIndex]);
  }
  else if(boxIndex == 2) {
    ampmIndex = (ampmIndex > 0) ? ampmIndex - 1 : 1; 
    snprintf(ampmChar, sizeof(ampmChar), "%s", currencyNameArray[ampmIndex]);
    text_layer_set_text(ampmBox, ampmChar);
  }
}

static void down_click_handler(ClickRecognizerRef recognizer, void *context) {
  if(boxIndex < 2) {
    int current = atoi(text_layer_get_text(numBox[boxIndex]));
    current = (current  > 0) ? current - 1 : 12; 
    snprintf(c[boxIndex], sizeof(c[boxIndex]), "%02d", current);
    text_layer_set_text(numBox[boxIndex], c[boxIndex]);
  }
  else if(boxIndex == 2) {
    ampmIndex = (ampmIndex < 1) ? ampmIndex + 1 : 0; 
    snprintf(ampmChar, sizeof(ampmChar), "%s", currencyNameArray[ampmIndex]);
    text_layer_set_text(ampmBox, ampmChar);
  }
}