Sony have adopted an intriguing approach to development for their SmartWatch 2.  Unlike other Smart Watches you don’t write code that runs on the watch itself.  Instead all your code runs on an Android phone.  You define the watch UI using standard Android layouts, and that UI is remoted onto the watch.

Your app can respond to events such as touches, since these events are sent from the watch to your phone, and then delivered to your app.

This is kind of cool, in that you don’t have to debug on the watch.  It is simpler, and I think it works well for relatively simple apps.

There are, however limitations on the UI elements that you can display.  Lists work well, but it isn’t currently possible to create a scrollable text area.

For the experimental app I was working on, this was a big issue. I needed to display text that went on for more than one screen.

I eventually found a way around this restriction.  I render the text into a bitmap in memory on the phone, then I split the bitmap up into watch-screen sized chunks, and I use each chunk as an element in a list.  This works.  You can scroll through your text, albeit a page at a time.

My list is derived from ManagedControlExtension, and in the onResume I render the text to a bitmap member variable by calling renderTextToCanvas:

  private void renderTextToCanvas() {
    mBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight * SCREEN_PAGES, Bitmap.Config.ARGB_8888);
    mBitmap.setDensity(DisplayMetrics.DENSITY_DEFAULT);
    mCanvas = new Canvas(mBitmap);
    mCanvas.setDensity(DisplayMetrics.DENSITY_DEFAULT);

    TextPaint tp = new TextPaint();
    tp.setColor(Color.WHITE);
    tp.setTextSize(18);

    String text = mNote.textContent;

    if(text == null) {
      Log.d(TAG, "Empty text ...");
      text = mContext.getString(R.string.empty_note);
      tp.setTextSkewX(-0.25f); // Italics
    }

    StaticLayout sl = new StaticLayout(text, tp, mScreenWidth, Layout.Alignment.ALIGN_NORMAL, 1.2f,
                                       0f, false);

    mCanvas.save();
    sl.draw(mCanvas);
    mCanvas.restore();
  }

Then when a list element is requested I render the appropriate bitmap chunk and return it:

@Override
  public void onRequestListItem(final int layoutReference, final int listItemPosition) {
    Log.d(TAG, "onRequestListItem() - position " + listItemPosition);
    if (layoutReference != -1 && listItemPosition != -1 && layoutReference == R.id.listView) {
      ControlListItem item = createControlListItem(listItemPosition);
      if (item != null) {
        sendListItem(item);
      }
    }
  }

  protected ControlListItem createControlListItem(int position) {
    Bitmap bitmap = Bitmap.createBitmap(mBitmap, 0, mScreenHeight * position,
                                                    mScreenWidth, mScreenHeight);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);

    ControlListItem item = new ControlListItem();
    item.layoutReference = R.id.listView;
    item.dataXmlLayout = R.layout.note_content_item;
    item.listItemPosition = position;
    item.listItemId = position;

    Bundle imageBundle = new Bundle();
    imageBundle.putInt(Control.Intents.EXTRA_LAYOUT_REFERENCE, R.id.imageView);
    imageBundle.putByteArray(Control.Intents.EXTRA_DATA, byteArrayOutputStream.toByteArray());

    item.layoutData = new Bundle[] { imageBundle };

    return item;
  }

All this leads to scrollable text: