While I am a huge fan of widgets on iOS, most apps miss the mark in terms of
what they offer via their widgets. Because I’m not one to settle, I have been on
a quest to build my own widgets so that I can get exactly what I desire.
Fortunately, I happened upon Scriptable (thanks Geoff!),
which makes it extremely easy to write your own iOS widgets with good ol’
JavaScript!
Sadly, the documentation kinda sucks, at least in terms of providing examples.
There is a gallery of scripts other folks have written, but it was pretty thin.
The content available was more in line with existing scripts that you could
leverage, and not clean examples of how to do things.
While writing my own widget, I had to figure out how to get things to align the
way I wanted them. Specifically, I wanted to be able to utilize the entire
widget area, and have everything space itself out accordingly. Essentially, I
wanted things to function like they do when using the flexible box (flexbox
)
in CSS.
Fortunately, Scriptable provides an addSpacer()
method, that you can pass in a
length value to. If you omit the length argument, or pass it a null
value, the
spacer will become flexible, and will consume any left over space.
Armed with this, you can center text or build out a grid system that will span
the entirety of the widget!
For demonstration purposes, I put together a script that creates a 9 by 9 grid,
that will stretch both horizontally and vertically to full the widget. Each area
has text that tells you which part of the widget it is (like a compass):
async function createWidget() {
const widget = new ListWidget
const layoutStack = widget.addStack
layoutStack.layoutVertically
const topStack = layoutStack.addStack
const northWestEl = topStack.addText('NW'
topStack.addSpacer
const northEL = topStack.addText('N'
topStack.addSpacer
const northEastEl = topStack.addText('NE'
layoutStack.addSpacer
const middleStack = layoutStack.addStack
const westEl = middleStack.addText('W'
middleStack.addSpacer
const centerEl = middleStack.addText('Center'
middleStack.addSpacer
const eastEl = middleStack.addText('E'
layoutStack.addSpacer
const bottomStack = layoutStack.addStack
const southWestEl = bottomStack.addText('SW'
bottomStack.addSpacer
const southEl = bottomStack.addText('S'
bottomStack.addSpacer
const southEastEl = bottomStack.addText('SE'
return widget
}
const widget = await createWidget
if (config.runsInWidget) {
Script.setWidget(widget
} else {
widget.presentLarge
}
Script.complete
The resulting widget looks like this (captured from the Scriptable macOS beta
app):