Skip to content

Instantly share code, notes, and snippets.

@Chronos2500
Created March 7, 2025 16:19
Show Gist options
  • Select an option

  • Save Chronos2500/66d1b18fda49a5c0c83485ab1f9fc321 to your computer and use it in GitHub Desktop.

Select an option

Save Chronos2500/66d1b18fda49a5c0c83485ab1f9fc321 to your computer and use it in GitHub Desktop.
import SwiftUI
//自作パッケージの切り出しなので変数名がめちゃくちゃです
//詳しくはこれの実装を見てください https://github.com/Chronos2500/CustomNavigationTitle
struct ContentView: View {
var body: some View {
NavigationStack{
ScrollView {
Color.blue.frame(height: 200)
.titleVisibilityAnchor()
Text("サンプルページ")
.frame(maxWidth: .infinity,alignment: .center)
}
.scrollAwareTitle()
}
}
}
struct BoundsPreferenceKey: PreferenceKey {
typealias Value = Anchor<CGRect>?
static let defaultValue: Value = nil
static func reduce(value: inout Value, nextValue: () -> Value) {
guard let newValue = nextValue() else { return }
value = newValue
}
}
extension View {
public func titleVisibilityAnchor() -> some View {
self.anchorPreference(
key: BoundsPreferenceKey.self,
value: .bounds
) { anchor in
anchor
}
}
}
private struct ScrollAwareTitleModifier: ViewModifier {
@State var isShowNavigationTitle = false
func body(content: Content) -> some View {
content
.backgroundPreferenceValue(BoundsPreferenceKey.self) { anchor in
GeometryReader { proxy in
if let anchor = anchor {
let scrollFrame = proxy.frame(in: .local).minY
let itemFrame = proxy[anchor]
let isVisible = (itemFrame.maxY + 22) > scrollFrame
DispatchQueue.main.async{
if isVisible {
isShowNavigationTitle = false
} else if !isVisible {
isShowNavigationTitle = true
}
}
}
return Color.clear
}
}
.toolbarBackgroundVisibility(.hidden, for: .navigationBar)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Image(systemName: "xmark.circle.fill")
.imageScale(.large)
.foregroundStyle(isShowNavigationTitle ? .blue : .red)
.animation(.easeIn(duration: 0.15), value: isShowNavigationTitle)
}
}
}
}
extension View {
public func scrollAwareTitle() -> some View {
modifier(ScrollAwareTitleModifier())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment