Bogdan Balan
Bogdan Balan

Reputation: 6701

How can one write a WatchOS widget for accessoryCorner family that renders appropriately?

I'm trying to build a widget that has a gauge like in the image attached. It does not seem like there are any APIs to render the gauge (or any other view for that matter) on an arc, depending on which corner is used.

Screenshoot

Is there any such support, or are such widgets only available to Apple? E.g. can one tell which corner the widget is being rendered in, so that the correct transformations be computed?

Thank you!

Upvotes: 7

Views: 1542

Answers (3)

OmniB
OmniB

Reputation: 111

Apple forums has a solution!

.widgetCurvesContent()

var body: some View {
    Text("Hi")
        .widgetCurvesContent()
        .widgetLabel("World!")
}

Upvotes: 8

TruMan1
TruMan1

Reputation: 36178

This was a bug introduced in watchOS 9.0 when they migrated Complications to WidgetKit, and still present as of watchOS 9.4. It has been an irritating issue that Apple refuses to acknowledge even though the curved design was present before; they downgraded it to mediocrity without warning.

Please contribute and complain on the Apple forums and also post Apple feedback. It was a big downgrade to the Complications with no warning and also misrepresented in the Human Interface Guideline.

Upvotes: 4

RyanM
RyanM

Reputation: 390

You can get close to an Apple style corner widget, but there are currently some limitations. As far as I know you have to use the .widgetLabel modifier which restricts you to an "Image, Text, Gauge, ProgressView, or a container with multiple subviews".

The styling for the Gauge and ProgressView seem to be predefined as well - for example styling the gauge with .gaugeStyle(LinearCapacityGaugeStyle()) doesn't change the appearance.

var body: some View {
      switch widgetFamily {
      case .accessoryCorner: // WatchOS only
         Text("50%") // Watch out for clipping
            .font(.system(size: 20))
            .foregroundColor(.blue)
            .widgetLabel {
               ProgressView(value: 0.5)
                  .tint(.blue)
            }
      }
}

or

var body: some View {
      switch widgetFamily {
      case .accessoryCorner: // WatchOS only
         Text("50%") // Watch out for clipping
            .font(.system(size: 20))
            .foregroundColor(.blue)
            .widgetLabel {
               Gauge(value: 50.0, in: 0...100) {
                  Text("Not shown")
               } currentValueLabel: {
                  Text("Not shown")
               } minimumValueLabel: {
                  Text("0") // Watch out for clipping
               } maximumValueLabel: {
                  Text("100") // Watch out for clipping
               }
               .tint(.blue)
               .gaugeStyle(LinearCapacityGaugeStyle()) // Doesn't do anything
            }

Gives you:

enter image description here enter image description here

You can rotate the text manually to try and make it line up with corner, but as you say then there doesn't seem to be a way to identify which corner the widget is in so you don't know which way to rotate it...

Upvotes: 7

Related Questions