首页 > 解决方案 > 尝试使用几何阅读器和导航栏获得全宽视图 - SwiftUI

问题描述

我有 2HStack使用几何阅读器将它们均匀地分成 2 个部分,这些部分嵌入到 aVStack中,我正在尝试创建类似于下图第一张的布局(iPad 上的横向模式)。

但是,我正在努力让HStack's 像中间的网格会议一样排列。我还有一个NavigationView侧边栏,它可以与HStacks 一起呈现,因此理想情况下 2 个图像会改变宽度但保持它们的高度,而不会挤压或拉伸图像。我曾尝试使用clipped().

下面的第二张图片是我运行代码时得到的。我已将此示例中的图像替换为 SFSymbol 以使其更易于调试。

所需的布局

当前布局

这是NavigationView我的侧边栏ContentView

struct SideBar: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: DetailView()) {
                    Label("Products", systemImage: "printer")
                }
                Label("Comparison", systemImage: "simcard.2")
                Label("Search", systemImage: "magnifyingglass")
            }
            .listStyle(SidebarListStyle())
            .navigationTitle("Navigation")
            
            DetailView()
        }
    }
}

这是包含内容的主视图:

struct DetailView: View {
    
    let title = "This is a title"
    let paragraph = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    let image = "dot.squareshape.fill"
    let intPadding: CGFloat = 10
    let extPadding: CGFloat = 40
    
    var body: some View {
        VStack(spacing: 0){
            GeometryReader { geometry in
                HStack(alignment: .top, spacing: 0){
                    Image(systemName:image)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: geometry.size.width / 2)
                        .clipped()
                    VStack(alignment: .leading) {
                        Text(title)
                            .font(.custom("Avenir-Heavy", size: 30))
                            .multilineTextAlignment(.leading)
                            .padding(.leading, intPadding)
                        Text(paragraph)
                            .font(.custom("Avenir", size: 16))
                            .multilineTextAlignment(.leading)
                            .lineSpacing(10)
                            .padding(.leading, intPadding)
                            .padding(.trailing, extPadding)
                    }
                    .frame(width: geometry.size.width / 2)
                }

            }
            GeometryReader { geometry in
                HStack(alignment: .top, spacing: 0){
                    Text(paragraph)
                        .font(.custom("Avenir", size: 16))
                        .multilineTextAlignment(.leading)
                        .lineSpacing(10)
                        .frame(width: geometry.size.width / 2)
                        .padding(.top, intPadding)
                        .padding(.trailing, intPadding)
                        .padding(.leading, extPadding)
                    Image(systemName:image)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: geometry.size.width / 2)
                        .offset(x: -intPadding)
                        .clipped()
                }
            }
        }
    }
}

编辑:

黑色方块代表图像要去的地方,我没有放黑色方块。所以上面提到的挤压和拉伸的想法应该看起来像下面的图像,所以它实际上并没有拉伸或挤压图像只是边界框:

在此处输入图像描述

标签: iosxcodeipadswiftui

解决方案


这是一个可能的方法的演示 - 使用Color.clear,因为它可以平等地填充所有可用的内容,并在叠加层中包含内容。

使用 Xcode 12.1 / iOS 14.1 准备

演示

var body: some View {
    VStack(spacing: 0) {
        Color.clear.overlay(
            HStack(spacing: 0) {
                    Color.clear.overlay(
                Image(systemName:image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    )
                    Color.clear.overlay(
                VStack(alignment: .leading) {
                    Text(title)
                        .font(.custom("Avenir-Heavy", size: 30))
                        .multilineTextAlignment(.leading)
                        .padding(.leading, intPadding)
                    Text(paragraph)
                        .font(.custom("Avenir", size: 16))
                        .multilineTextAlignment(.leading)
                        .lineSpacing(10)
                        .padding(.leading, intPadding)
                        .padding(.trailing, extPadding)
                }
                    , alignment: .top)
                },
        alignment: .top)
        Color.clear.overlay(
            HStack(spacing: 0) {
                    Color.clear.overlay(
                Text(paragraph)
                    .font(.custom("Avenir", size: 16))
                    .multilineTextAlignment(.leading)
                    .lineSpacing(10)
                    .padding(.top, intPadding)
                    .padding(.trailing, intPadding)
                    .padding(.leading, extPadding)
                    , alignment: .top)
                    Color.clear.overlay(
                Image(systemName:image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .clipped()
                    , alignment: .top)
            }
        )
    }
}

更新:全屏变体

演示2

        VStack(spacing: 0) {
            Color.clear.overlay(
                HStack(spacing: 0) {
                        Color.black
//                      .overlay(
//                    Image(systemName:image)
//                        .resizable()
//                        .aspectRatio(contentMode: .fit)
//                      )
                        Color.clear.overlay(
                    VStack(alignment: .leading) {
                        Text(title)
                            .font(.custom("Avenir-Heavy", size: 30))
                            .multilineTextAlignment(.leading)
                            .padding(.leading, intPadding)
                        Text(paragraph)
                            .font(.custom("Avenir", size: 16))
                            .multilineTextAlignment(.leading)
                            .lineSpacing(10)
                            .padding(.leading, intPadding)
                            .padding(.trailing, extPadding)
                    }
                        , alignment: .top)
                    },
            alignment: .top)
            Color.clear.overlay(
                HStack(spacing: 0) {
                        Color.clear.overlay(
                    Text(paragraph)
                        .font(.custom("Avenir", size: 16))
                        .multilineTextAlignment(.leading)
                        .lineSpacing(10)
                        .padding(.top, intPadding)
                        .padding(.trailing, intPadding)
                        .padding(.leading, extPadding)
                        , alignment: .top)
                        Color.black
//                      .overlay(
//                    Image(systemName:image)
//                        .resizable()
//                        .aspectRatio(contentMode: .fit)
//                        .clipped()
//                      , alignment: .top)
                }
            )
        }
        .navigationBarHidden(true)
        .edgesIgnoringSafeArea(.all)
    }

推荐阅读