Good scriptable lockscreen widget tutorial and resource?

Now that we can make lockscreen widgets in Scriptable(which is totally awesome by the way). Any good resource or tutorials available out there?

1 Like

Making widgets for the lock screen isn’t much different from regular widgets.

There are just some points to consider. Hopefully this list would help.

  • Colours sort of come out as grayscale. You’ll need to experiment which one to use if you want to make them distinguishable from each other
  • Space is limited. Consider the font sizes you use and whenever appropriate, assign a minimumScaleFactor for text content.
  • There’s native background transparency using the addAccessoryWidgetBackground property of ListWidget.
  • Content of circular widgets are best cantered. But not mandatory of course. You do you.
  • You can’t customise sizes and fonts of the inline widget (the one above the clock). Don’t even try. It’s best for one liner info.
  • You can’t add multiple images on the inline widget. just one and it will appear before the text. Emojis are ok though.
  • WidgetDate where the text dynamically updates every seconds works on the rectangular and circular widgets, but not on the inline widget.

These are the quirks and behaviours I’ve found so far. I’ll update if I find anything else.

Example Widget

6 Likes

Thanks man, really appreciate it! Good to know that making lockscreen widgets is pretty similar to making regular widgets. :grin:

Anyone know if it is possible to create those circles that temperature and fitness are using?
image

I’m no expert in making graphical stuff with scriptable but I see others doing it by making the graphic in a <canvas> element inside a WebView then exporting it from there.

1 Like

Since last week I saw we can add Scriptables in the Lockscreen in the date box. (See my screenshot) Who has used that already? Any examples? :thinking:

So glad I found your post, thanks. I was trying to find changes to the Scriptable docs with the release of lockscreen widget support, and it seems the online docs are not updated (and missing addAccessoryWidgetBackground) while the in-app docs are.

@simonbs if there’s any version history for docs that can be made publicly available that would be much appreciated :pray:


For anyone else interested, I believe these are the only lockscreen-widget-specific changes, all additions to ListWidget:

addAccessoryWidgetBackground: boolean;
presentAccessoryCircular: () => Promise<void>;
presentAccessoryInline: () => Promise<void>;
presentAccessoryRectangular: () => Promise<void>;

I may have missed something though.

Yes, using DrawContext, .strokeEllipse etc.

Here’s a reimplementation of the circular range widget (left) with the temperature widget (right). Transparent masking doesn’t seem possible with DrawContext so that would require another approach.

Screenshot 2022-11-22 at 7.35.21 pm

function circularRange(val, min, max, width, height) {
  let context = new DrawContext()
  context.size = new Size(width, height)
  context.respectScreenScale = true
  context.opaque = false
  
  // background
  let rect = new Rect(0, 0, width, height)
  context.setFillColor(Color.black())
  context.fillRect(rect)

  // ring
  let lineWidth = 16
  context.setLineWidth(lineWidth)
  let ring = new Rect(lineWidth/2, lineWidth/2, width - lineWidth, height - lineWidth)
  context.setStrokeColor(Color.gray())
  context.strokeEllipse(ring)

  // mask
  let path = new Path()
  path.move(new Point(width / 2, height / 2))
  let end = Math.PI / 6
  let my = ((1 + Math.tan(end)) / 2) * height
  path.addLine(new Point(0, my))
  path.addLine(new Point(0, height))
  path.addLine(new Point(width, height))
  path.addLine(new Point(width, my))
  context.addPath(path)
  context.setFillColor(Color.black())
  context.fillPath()

  // rounded ends
  let lx = ((1 - Math.cos(end)) / 2) * (width - lineWidth)
  let ly = ((1 + Math.sin(end)) / 2) * (height - lineWidth)
  let lend = new Rect(lx, ly, lineWidth, lineWidth)
  let rx = ((1 + Math.cos(end)) / 2) * (width - lineWidth)
  let rend = new Rect(rx, ly, lineWidth, lineWidth)
  context.setFillColor(Color.gray())
  context.fillEllipse(lend)
  context.fillEllipse(rend)

  // value
  let a = (195 - (val - min) / (max - min) * 210) * Math.PI / 180
  let vx = ((1 + Math.cos(a)) / 2) * (width - lineWidth)
  let vy = ((1 - Math.sin(a)) / 2) * (height - lineWidth)
  let value = new Rect(vx, vy, lineWidth, lineWidth)
  context.setLineWidth(lineWidth * 3/4)
  context.setStrokeColor(Color.black())
  context.strokeEllipse(value)
  context.setFillColor(Color.white())
  context.fillEllipse(value)

  // labels
  context.setTextColor(Color.white())
  context.setFont(Font.mediumSystemFont(72))
  context.setTextAlignedCenter()
  context.drawTextInRect(val.toString(), new Rect(width/4, height/4, width/2, height/2))
  context.setFont(Font.regularSystemFont(32))
  context.setTextAlignedLeft()
  context.drawTextInRect(min.toString(), new Rect(width/5, height * 7/10, width * 3/10, height * 3/10))
  context.setTextAlignedRight()
  context.drawTextInRect(max.toString(), new Rect(width/2, height * 7/10, width * 3/10, height * 3/10))

  return context
}

let widget = new ListWidget()
widget.setPadding(0, 0, 0, -8)
let image = circularRange(16, 6, 18, 175, 175).getImage()
widget.addImage(image)
if (config.runsInAccessoryWidget) {
  Script.setWidget(widget)
} else {
  widget.presentSmall()
}

A couple more

  • config.runsInAccessoryWidget
  • config.widgetFamily adds 3 more values - accessoryRectangular, accessoryInline, and accessoryCircular
1 Like

Thank you for all answers. I have now done a few Lock Screen widgets and will share them here
flopp999/Scriptable (github.com)