使 ScrollView 中的标题在下拉时粘在顶部,也可以选择在下拉时使其拉伸

问题描述 投票:0回答:1

我想在 SwiftUI 中重新创建名为 Gentler Streaks 的应用程序的行为。似乎有一个由图像表示的标题,当下拉时,它会粘在视图的顶部并且图像会拉伸。

期望的结果

在我的应用程序中,我有一个带有两个图像的标题,不知道该怎么做,代码如下。

我的应用程序


import SwiftUI
import MapKit

struct PredatorDetail: View {
    let predator: ApexPredator
    @State var position: MapCameraPosition

    
    var body: some View {
        GeometryReader {geo in
            ScrollView {
                Section {
                    LazyVStack(alignment: .leading) {
                        //dino name
                        Text(predator.name)
                            .font(.largeTitle)
                        
                        //current location
                        NavigationLink {
                            PredatorMap(position: .camera(MapCamera(centerCoordinate: predator.location, distance: 1000, heading: 250, pitch: 80)))
                        } label: {
                            Map(position: $position) {
                                Annotation(predator.name, coordinate: predator.location) {
                                    Image(systemName: "mappin.and.ellipse")
                                        .font(.largeTitle)
                                        .imageScale(.large)
                                        .symbolEffect(.pulse)
                                }
                                .annotationTitles(.hidden)
                            }
                            .frame(height: 125)
                            
                            .overlay(alignment: .trailing) {
                                Image(systemName: "greaterthan")
                                    .imageScale(.large)
                                    .font(.title3)
                                    .padding(.trailing, 5)
                            }
                            .overlay(alignment: .topLeading) {
                                Text("Current Location")
                                    .padding([.leading, .bottom], 5)
                                    .padding(.trailing, 8)
                                    .background(.black.opacity(0.7))
                                    .clipShape(.rect(bottomTrailingRadius:15))
                            }
                            .clipShape(.rect(cornerRadius: 15))
                        }
                        
                        // apears in
                        Text("Appears In:")
                            .font(.title3)
                        
                        ForEach(predator.movies, id: \.self) { movie in
                            Text("•" + movie)
                                .font(.subheadline)
                        }
                        // move momens
                        Text("Movie Moments:")
                            .font(.title)
                            .padding(.top, 15)
                        
                        ForEach(predator.movieScenes) { scene in
                            Text(scene.movie)
                                .font(.title2)
                                .padding(.vertical, 1)
                            Text(scene.sceneDescription)
                                .padding(.bottom, 15)
                            
                            
                            
                        }
                        Text("Read More")
                            .font(.caption)
                        
                        Link(predator.link, destination: URL(string: predator.link)!)
                            .font(.caption)
                            .foregroundStyle(.blue)
                        
                        
                        // link to webpage
                    }
                    .padding()
                    .padding(.bottom, 30)
                    .frame(width: geo.size.width, alignment: .leading)
                } header: {
                    ZStack (alignment: .bottomTrailing) {
                        // backgorund image
                        Image(predator.type.rawValue)
                            .resizable()
                            .scaledToFit()
                            .overlay {
                                LinearGradient(stops: [Gradient.Stop(color: .clear, location: 0.8), Gradient.Stop(color: .black, location: 1)], startPoint: .top, endPoint: .bottom)
                            }
                        // dino image
                        Image(predator.image)
                            .resizable()
                            .scaledToFit()
                            .frame(width: geo.size.width/1.5, height: geo.size.height/3)
                            .scaleEffect(x: -1)
                            .shadow(color: .black, radius: 7)
                            .offset(y: 30)
                        
                    }
                    .padding(.bottom, 10)
                }
            }
            .ignoresSafeArea()
        }
        .toolbarBackground(.automatic)
    }
}

#Preview {
    PredatorDetail(predator: Predators().apexPredators[10], position: .camera(MapCamera(centerCoordinate: Predators().apexPredators[10].location, distance: 30000)))
        .preferredColorScheme(.dark)
}

我其实很无知,没有找到解决办法。

swiftui
1个回答
0
投票

您可以使用

onScrollGeometryChange
来检测滚动视图何时“过度滚动”。这是当
contentOffset.y + contentInsets.top
小于 0 时。您可以使用该值来确定图像应该大多少。

例如:

struct ContentView: View {
    @State var scale: CGFloat = 1
    @State var offset: CGFloat = 0
    var body: some View {
        ScrollView {
            Section {
                ForEach(0..<100) { _ in
                    Text("Scrollable Content")
                        .frame(maxWidth: .infinity)
                }
            } header: {
                Image("some image")
                    .resizable()
                    .frame(width: 100, height: 100)
                    .scaleEffect(scale, anchor: .top)
                    .offset(y: offset)
            }
        }
        .onScrollGeometryChange(for: CGFloat.self) { geo in
            -min(0, geo.contentOffset.y + geo.contentInsets.top)
        } action: { _, overscrolledAmount in
            scale = 1 + (overscrolledAmount / 150)
            offset = -overscrolledAmount
        }
    }
}

这里我使用了

1 + (overscrolledAmount / 150)
,因此比例随着过度滚动的量线性变化。尝试尝试不同类型的关系(对数、平方根等)。

我还将图像向上偏移了过度滚动的量,这样它就不会与其他内容一起向下滚动。

© www.soinside.com 2019 - 2024. All rights reserved.