【SwiftUI】ぼかしのナビゲーションバー

# はじめに
https://twitter.com/SNQ2001/status/1676969904359211008?s=20

# 実装
```swift
import SwiftUI

extension View {
    func onChangeParentScrollViewOffset(perform: @escaping (CGFloat) -> Void) -> some View {
        self.background(GeometryReader {
            Color.clear.preference(
                key: OffsetYPreferenceKey.self,
                value: $0.frame(in: .global).origin.y
            )
        }).onPreferenceChange(
            OffsetYPreferenceKey.self,
            perform: perform
        )
    }
}

struct OffsetYPreferenceKey: PreferenceKey {
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value += nextValue()
    }
}
```

```swift
import SwiftUI

struct NavigationBlurView<T: View>: View {
    @State private var offsetY = CGFloat.zero
    
    private var title: String

    private var navigationHeight: CGFloat
    
    private var content: () -> T
    
    init(_ title: String, navigationHeight: CGFloat = 70.0, content: @escaping () -> T) {
        self.title = title
        self.navigationHeight = navigationHeight
        self.content = content
    }

    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            content()
                .padding(.top, navigationHeight + 30)
                .onChangeParentScrollViewOffset { offsetY in
                    self.offsetY = offsetY
                }
        }
        .overlay(alignment: .top, content: navigationBar)
        .animation(.spring(), value: offsetY)
    }

    private func navigationBar() -> some View {
        ZStack(alignment: .center) {
            Color.clear.background(.ultraThinMaterial.opacity(offsetY < 0 ? 1 : 0))
                .padding(.top, -navigationHeight)
                .padding(.horizontal, -20)
                .blur(radius: 15)

            HStack(spacing: 15) {
                Text(title)
                    .font(.system(size: offsetY < 0 ? 25 : 30))
                    .fontWeight(.heavy)
                    .foregroundStyle(.white)
                    .lineLimit(1)

                Spacer()

                Button {
                } label: {
                    Image(systemName: "yensign.circle.fill")
                        .foregroundStyle(offsetY < 0 ? .white : .purple)
                }
                .padding(5)
                .background(.thickMaterial, in: RoundedRectangle(cornerRadius: 10))
                
                Button {
                } label: {
                    Image(systemName: "moon.haze.fill")
                        .foregroundStyle(offsetY < 0 ? .white : .purple)
                }
                .padding(5)
                .background(.thickMaterial, in: RoundedRectangle(cornerRadius: 10))
            }
            .frame(maxWidth: .infinity)
            .padding(.top, offsetY < 0 ? 0 : 10)
            .padding(.horizontal, 20)
        }
        .frame(height: navigationHeight, alignment: .top)
    }
}
```

# 使い方
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationBlurView("NavigationBlur") {
            VStack(spacing: 10) {
                ForEach(0..<100) { _ in
                    Image("sample")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(maxWidth: .infinity)
                }
            }
        }
    }
}
```

# おわり
右側のボタンもカスタムできるようにしたらライブラリにでもしようかな、、、