BLACK FRIDAY: Save 50% on all my books and bundles! >>

How to dynamically adjust the appearance of a view based on its size and location

Paul Hudson    @twostraws   

Updated for Xcode 16.4

New in iOS 17

SwiftUI’s visualEffect() modifier lets us read the geometry proxy for a view without using a GeometryReader, which means we can look at the size and location of a view without affecting its layout behavior.

Important: This modifier is specifically for applying visual effects such as adjusting colors or adding blur, and cannot adjust how the frame of your content is calculated for layout purposes. It can adjust frame-like things such as the offset and scale of your view, because they don’t affect layout.

As an example, the following code blurs each view in a scroll view by some blur amount that’s calculated by how far away the view is away from the center of its scroll view. That means views near the vertical center have little or no blur, whereas views on the outside are heavily blurred:

struct ContentView: View {
    var body: some View {
        ScrollView {
            ForEach(0..<100) { i in
                Text("Row \(i)")
                    .font(.largeTitle)
                    .frame(maxWidth: .infinity)
                    .visualEffect { content, proxy in
                        content.blur(radius: blurAmount(for: proxy))
                    }
            }
        }
    }

    func blurAmount(for proxy: GeometryProxy) -> Double {
        let scrollViewHeight = proxy.bounds(of: .scrollView)?.height ?? 100
        let ourCenter = proxy.frame(in: .scrollView).midY
        let distanceFromCenter = abs(scrollViewHeight / 2 - ourCenter)
        return Double(distanceFromCenter) / 100
    }
}

Download this as an Xcode project

A scrolling list of rows, where rows near the center are sharp and rows near the edges are blurry.

Tip: Calling proxy.frame(in: .scrollView) finds the size of this view in the innermost scroll view that contains it.

These visual effects work with any kind of position, including that generated through animation. For example, this makes a series of circles in a grid spin around, with each one dynamically recoloring based on a hue rotation:

struct ContentView: View {
    @State private var rotationAmount = 0.0

    var body: some View {
        Grid {
            ForEach(0..<3) { _ in
                GridRow {
                    ForEach(0..<3) { _ in
                        Circle()
                            .fill(.green)
                            .frame(width: 100, height: 100)
                            .visualEffect { content, proxy in
                                content.hueRotation(.degrees(proxy.frame(in: .global).midY / 2))
                            }
                    }
                }
            }
        }
        .rotationEffect(.degrees(rotationAmount))
        .onAppear {
            withAnimation(.linear(duration: 5).repeatForever(autoreverses: false)) {
                rotationAmount = 360
            }
        }
    }
}

Download this as an Xcode project

A 3x3 grid of rotating circles, where each circle changes colors as it moves.

The modifier’s name, visualEffect(), should make it clear that any adjustments you make are limited how the finished view looks – if you find yourself wanting to use it to adjust view content, you’re looking in the wrong place.

Save 50% in my Black Friday sale.

SAVE 50% All our books and bundles are half price for Black Friday, so you can take your Swift knowledge further for less! Get my all-new book Everything but the Code to make more money with apps, get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn Swift Testing, design patterns, and more.

Save 50% on all our books and bundles!

Similar solutions…

BUY OUR BOOKS
Buy Everything but the Code Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Interview Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 5.0/5

 
Unknown user

You are not logged in

Log in or create account