Chapters

Hide chapters

watchOS With SwiftUI by Tutorials

First Edition · watchOS 8 · Swift 5.5 · Xcode 13.1

Section I: watchOS With SwiftUI

Section 1: 16 chapters
Show chapters Hide chapters

11. Tinted Complications
Written by Scott Grosch

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

The default setting for the Apple Watch shows complications in full-color. When selecting and populating a watch face, the user may instead choose to select a tint color. If they select a tint, all elements on the watch face will change to honor the selected tint color.

Full-color

Open Happy.xcodeproj from this project’s starter materials. Then press Control‑0 (that’s a zero) to select the Happy WatchKit App (Complication) scheme. This chapter focuses solely on the complication, not the app itself, so switching to the complication scheme makes sense instead of running the app.

Build and run. Once launched, long-press the watch face to bring up the face editor:

Then swipe left to get to the add new face screen:

Tap Add, then scroll to the bottom of the list to select the X-Large face:

Once you’ve tapped Add, the color selection screen will appear. Scroll to the MULTICOLOR choice if it’s not already selected:

Swipe left again to see the empty complications screen.

After tapping the empty square, scroll down to the Happy app:

Tap to select it, then press the home button twice.

Looks amazing, right? :]

What happens when the watch face is tinted?

Desaturation

By default, if the user selects a tint color for the watch face, watchOS will desaturate the full-color image. Desaturation is the process of making colors more muted. By adding more black or white to the image, the colors become less vibrant. The more you desaturate an image, the more color you remove.

Layered images

When you require more control over how the image looks while tinted, you can split it into two separate images. For example, consider the smiley-face image you’re using to have two separate parts. The circular part of the face, in green, is the background. The eyes and mouth are then the foreground.

// 1
guard
  let full = UIImage(named: "Full"),
  let background = UIImage(named: "Background"),
  let eyesAndMouth = UIImage(named: "eyesAndMouth")
else {
  fatalError("Images are missing from the asset catalog.")
}

let template = CLKComplicationTemplateGraphicExtraLargeCircularImage(
  imageProvider: CLKFullColorImageProvider(
    // 2
    fullColorImage: full,
    // 3
    tintedImageProvider: .init(
      // 4
      onePieceImage: full,
      // 5
      twoPieceImageBackground: background,
      // 6
      twoPieceImageForeground: eyesAndMouth
    )
  )
)

SwiftUI complications

SwiftUI graphic complication views also support tinting but with a different syntax.

Image("Full")
  .resizable()
  .aspectRatio(contentMode: .fit)

Desaturation

By default, SwiftUI complications will be desaturated, like the non-SwiftUI versions. Add ClockKit to the top of the file:

import ClockKit
CLKComplicationTemplateGraphicExtraLargeCircularView(
  HappyComplication()
)
  .previewContext()
// 1
Group {
  // 2
  ForEach(CLKComplicationTemplate.PreviewFaceColor.allColors) {
    CLKComplicationTemplateGraphicExtraLargeCircularView(
      HappyComplication()
    )
      // 3
      .previewContext(faceColor: $0)
  }
}

Layered

To use layered tinting, change the image name from Full to eyesAndMouth. Next, add another modifier to the Image like so:

.complicationForeground()
ZStack {
  Circle()

  // The Image here
}

Rendering modes

There will be times when you still want a bit more control, depending on whether the user tints the watch face. SwiftUI has you covered!

@Environment(\.complicationRenderingMode) var renderingMode
ZStack {
  // 1
  if renderingMode == .fullColor {
    // 2
    Image("Full")
      .resizable()
      .aspectRatio(contentMode: .fit)
      .complicationForeground()
  } else {
    // 3
    Circle()

    Image("eyesAndMouth")
      .resizable()
      .aspectRatio(contentMode: .fit)
      .complicationForeground()
  }
}
.fill(LinearGradient(
  gradient: Gradient(
    colors: [.red.opacity(0.3), .blue.opacity(1.0)]
  ),
  startPoint: .top,
  endPoint: .bottom))

Update the complication controller

So far, you’ve performed all of your previewing of the complication from Xcode’s Canvas. Remember, to let the user pick your updated complication you must import SwiftUI in ComplicationController.swift:

import SwiftUI
let template = CLKComplicationTemplateGraphicExtraLargeCircularView(
  HappyComplication()
)

return .init(date: Date.now, complicationTemplate: template)

Key points

  • Be sure to look at your complications on tinted watch faces.
  • Split your Image or Shape items into foreground and background layers.
  • When using tinted complications, watchOS ignores the color and only honors the opacity.

Where to go from here?

In the following chapter, you’ll continue to use complications. But this time, you will focus on SwiftUI complications to round up your knowledge on this useful and sometimes underestimated Apple Watch feature. If you want to get a hint of what to expect:

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now