如何实现像iPhone设置那样的Form滚动视觉效果

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

我想实现下面的视觉呈现。一个表单,包括 iPhone 的“设置”应用程序等部分,但顶部有一个圆形视觉元素。我希望它们一起滚动并具有相同的背景颜色。

enter image description here

代码:

NavigationStack {
    HStack {
        Image("JoinUs") // Demo purpose
            .resizable()
            .frame(maxWidth: 360)
            .aspectRatio(contentMode: .fit)
    }
    .background(.green)
    .mask { RoundedRectangle(cornerRadius: 25) }
    .padding()
    
    Form {
        Section {
            Text("Voice")
            Text("Speed")
            Text("Pitch")
            Text("Voice")
        } header: {
            Text("Sound")
        }
        
        Section {
            Text("Text Size")
        } header: {
            Text("System")
        }
        
        Section {
            Text("Voice")
            Text("Speed")
            Text("Pitch")
            Text("Voice")
        } header: {
            Text("Sound")
        }
        
        Section {
            Text("Voice")
            Text("Speed")
            Text("Pitch")
            Text("Voice")
        } header: {
            Text("Sound")
        }
    }
    .navigationTitle("Settings")

这是我得到的:

enter image description here

我观察到的两个问题:

  • HStack 顶部视图的白色背景。 -> 如何显示相同的背景颜色,在本例中为灰色。
  • 每次表单滚动时,顶部的 HStack 视图不会滚动 -> 尝试将其放入表单中,可以一起滚动,但尺寸较小,并且还有白色背景问题。

enter image description here

ios swiftui layout
1个回答
0
投票

1.隐藏默认表单背景

添加此行:

.scrollContentBackground(.hidden)

2.隐藏分隔线

您可以在每个

Section
:

上添加此行
.listRowSeparator(.hidden)

或创建您的

UnseparatedSection
以轻松重复使用:

struct UnseparatedSection<Content: View, Header: View>: View {
    let content: Content
    let header: Header
    
    init(@ViewBuilder content: () -> Content,
         @ViewBuilder header: () -> Header) {
        self.content = content()
        self.header = header()
    }
    
    var body: some View {
        Section {
            content
        } header: {
            header
        }
        .listRowSeparator(.hidden)
    }
}

3.设计
NavigationLink

struct CustomNavigationLink<Destination: View, Label: View>: View {
    let image: ImageResource
    let destination: Destination
    let label: Label
    
    init(image: ImageResource,
         @ViewBuilder destination: () -> Destination,
         @ViewBuilder label: () -> Label) {
        self.destination = destination()
        self.label = label()
        self.image = image
    }
    
    var body: some View {
        NavigationLink {
            destination
        } label: {
            HStack {
                Image(image)
                    .padding(.trailing, 8)
                label
            }
        }
        .frame(maxWidth: .infinity,
               maxHeight: .infinity,
               alignment: .leading)
        .padding(.vertical, 5)
        .padding(.horizontal, 15)
        .background{
            RoundedRectangle(cornerRadius: 15)
                .fill(.gray.opacity(0.2))
        }
    }
}

您的最终代码:

NavigationStack {
    Form {
        Image(.demo)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(maxWidth: 360)
            .mask { RoundedRectangle(cornerRadius: 25) }
        
        UnseparatedSection {
            CustomNavigationLink(image: .icon) {
                /*TODO: Add Destination View*/
            } label: {
                Text("Voice")
            }
            CustomNavigationLink(image: .icon) {
                /*TODO: Add Destination View*/
            } label: {
                Text("Speed")
            }
            CustomNavigationLink(image: .icon) {
                /*TODO: Add Destination View*/
            } label: {
                Text("Pitch")
            }
            CustomNavigationLink(image: .icon) {
                /*TODO: Add Destination View*/
            } label: {
                Text("Voice")
            }
        } header: {
            Text("Sound")
        }

        //...
    }
    .navigationTitle("Settings")
    .scrollContentBackground(.hidden)
}
© www.soinside.com 2019 - 2024. All rights reserved.