Marquee Effect in SwiftUI

Marquee Effect is when a long-view (typically text-based) has its content moving horizontally to disclose full content. Like this: It’s fairly simple (albeit not straightforward) to do in SwiftUI. Android’s Jetpack Compose has it out of the box. As does also HTML: <marquee>. In this tutorial we’re going to use shaders and .distortionEffect modifier so this solution will be working for iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0 and further. This tutorial also goes through the process step-by-step, if you just need the full code, I’m leaving it in the end of this blogpost. ...

March 15, 2024 · 7 min

Custom icon for SwiftUI MenuBarExtra

If you tired already the new API for macOS Ventura - MenuBarExtra - you might have stumbled upon the fact that while SF Symbols work just great for the Manu Bar Icon, custom icons aren’t working as expected. There’s no obvious reason for that, looks like SwiftUI is doing some trickery under the hood and this trickery isn’t really adjustable. But there’s a way of making it work, so let’s dive right in and see what works and what doesn’t! ...

December 13, 2022 · 2 min

Glare effect in SwiftUI

In this blogpost we’re going to create this fancy glare effect in SwiftUI: The effect kinda shows the glancing texture of View’s surface. Essentially the effect consists of a main View and a mask blended together. Let’s add a text and style it first: 1 2 3 4 5 6 7 let glareView = Text("Hello world!") .font(.system(size: 50, weight: .heavy, design: .rounded)) .foregroundStyle(LinearGradient( colors: [.blue, .mint], startPoint: .topLeading, endPoint: .bottomTrailing )) Here’s how it looks like: Now, the glare “line” is this very view masked by an animated Rectangle. Let’s implement that mask: ...

December 13, 2022 · 6 min

OS version availability check in @SceneBuilder

There are times when you might need to show different root views depending on the available OS version. For example you may have a new API that can be only used in the latest OS version. The problem with this is that body of your App structure wouldn’t allow that: 1 2 3 4 5 6 7 8 9 10 @main struct YourApp: App { var body: some Scene { if #available macOS(13.0, *) { // Error ... } else { ... } } } The reason is that implicitly body of the App is @SceneBuilder (the same way body of the View is implicitly a @ViewBuilder) and @SceneBuilder doesn’t allow to have a version check inside it. It would be allowed in an ordinary property though, like this: ...

January 13, 2022 · 1 min