swiftui 无法使用几何读取器使细胞机器人在 Avery 设备上的纵向和横向看起来不错

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

支持 iOS 15。使用此代码,我会得到一个带有图像和文本的垂直单元格,如果有通知,我会显示红色圆形文本。事情发生在我的手机上,我的手机延伸得太远,通知距离太远。我尝试的任何解决方案如果解决了 iPad 问题,也许会将红色标签居中,而不是将其放在右上角。

  • 在 iPhone 11 纵向上 - 一切正常
  • 在 iPhone 11 横屏上 - 通知设置有点太远了
  • 在 iPad 10 上,横向通知距离很远

iPhone 肖像

iPad 横向

导入 SwiftUI

struct FavouritesWebAppsMainView: View {
    
    @EnvironmentObject var classFromEntryPoint: ClassFromEntryPoint

    //code for presenting sheet.
    @State private var selectedItem: WebAppModel?
    //related to customized wkwebViews
    @State private var errorMessage: String = "none"
    @State private var showAlert = false
    
    let columns = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible()),
    ]
    
    var body: some View {
        VStack {
            headerView
            mainBodyWithGrid
            .sheet(item: $selectedItem) { webApp in
                let test = webApp.appUrl
                if let url = URL(string: test) {
                    CustomWebView(url: url, messageErrorFromWebView: $errorMessage)
                    HStack {
                        Spacer()
                        Button(action: {
                            selectedItem = nil //Used to dismiss the sheet
                        }) {
                            Label("", systemImage: "xmark")
                        }
                    }
                    .padding()
                    .background(Color.gray.opacity(0.2))
                } else {
                    //never called
                    let _ = self.errorMessage = "Not valid URL"
                    let _ = self.showAlert = true
                    let _ = Logger.error("failed url: \(webApp.appUrl)")
                }
            }
        } //most external view
        .backgroundImage()

        .onChange(of: errorMessage, perform: { newValue in
            self.showAlert = true
        })
        .alert("Errore", isPresented: $showAlert) {
            Button("ok", role: .cancel) {}
        } message: {
            Text(self.errorMessage)
        }
    }
    
    //MARK: single views
    private var headerView: some View {
        VStack {
            HStack {
                Text("Welvome")
                    .font(.largeTitle)
                    .foregroundColor(.blue)
                    .lineLimit(1)
                    .minimumScaleFactor(0.5)
                    .padding()
                Spacer()
            }
            Text("Le tue app")
                .padding(.bottom)
        }
    }
    
    private var mainBodyWithGrid: some View {
        ZStack(alignment: .bottom) {
            ScrollView {
                if classFromEntryPoint.preferredAppList.isEmpty {
                    Text("Add App to the store")
                } else {
                    LazyVGrid(columns: columns, spacing: 30) {
                        ForEach(classFromEntryPoint.preferredAppList) { item in
                            VerticalCellView(item: item)
                                .onTapGesture {
                                    self.selectedItem = item
                                }
                        }
                    }
                    .padding(.horizontal)
                }
            }
            
            logoutButton
        }
    }
    
    private var logoutButton: some View {
        HStack {
            Button("Logout") {
                Logger.debug("logout")
                classFromEntryPoint.performLogout()
            }
            .padding()
            .background(.red)
            .foregroundStyle(.white)
            .clipShape(Capsule())
            .padding()
            Spacer()
        }
    }

    
}


//MARK: - cell

struct VerticalCellView: View {

    var item: WebAppModel

    var body: some View {
        ZStack(alignment: .topTrailing) {
            GeometryReader { geometry in
                VStack {
                    ImageDownloadedFromWeb(url: item.logoUrl ?? "N/D")
                        .frame(width: min(geometry.size.width, 100), height: min(geometry.size.width, 100))
                    Text(item.name)
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                    //                            Text(item.description)
                    //                                .font(.subheadline)
                    //                                .lineLimit(2)
                    //                                .truncationMode(.tail)
                }
                .frame(width: geometry.size.width)
            }
            let notificationCount = (Int.random(in: 0...20))
            Text(notificationCount > 10 ? "99+" : "\(notificationCount)")
                            .font(.system(size: 12))
                            .frame(width: 25, height: 25)
                            .background(.red)
                            .foregroundColor(.white)
                            .clipShape(Circle())
        }
        .frame(height: 150)
    }
}

可能的解决方案,但不清楚为什么它有效

struct VerticalCellView: View {

    var item: WebAppModel

    var body: some View {
        VStack {
            ImageDownloadedFromWeb(url: item.logoUrl ?? "N/D")
                .frame(width: 100, height: 100)
                .overlay(
                    notificationBadge,
                    alignment: .topTrailing
                )
            Text(item.name)
                .font(.headline)
            //                            Text(item.description)
            //                                .font(.subheadline)
            //                                .lineLimit(2)
            //                                .truncationMode(.tail)
        }
        .frame(height: 150)
    }

    private var notificationBadge: some View {
        let notificationCount = (Int.random(in: 0...20))
        return Text(notificationCount > 10 ? "99+" : "\(notificationCount)")
            .font(.system(size: 12))
            .frame(width: 25, height: 25)
            .background(.red)
            .foregroundColor(.white)
            .clipShape(Circle())
            .offset(x: 10, y: -10)
    }
}
list swiftui cell geometryreader
1个回答
0
投票

为了跟进评论,我建议将徽章显示为图像上的叠加层。这样,徽章就永远不会与图像分离。

你说你试过了,但没有成功,所以我自己也尝试了一下。我发现自己在想,你为什么要使用

GeometryReader
?它给你的大小是网格单元的大小,但这并不是特别有用。

这是示例的精简版本,用于说明如何使用叠加层来实现此目的。本着最小可重现示例的精神,我遗漏了所有不需要或相关的内容。

struct WebAppModel: Identifiable {
    let id = UUID()
    let logo: String
    let name: String
}

struct FavouritesWebAppsMainView: View {

    let items: [WebAppModel] = [
        WebAppModel(logo: "lizard", name: "test1"),
        WebAppModel(logo: "ant", name: "test2"),
        WebAppModel(logo: "tortoise", name: "test3"),
        WebAppModel(logo: "fossil.shell", name: "test4"),
    ]

    let columns = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible()),
    ]

    var body: some View {
        mainBodyWithGrid
    }

    private var mainBodyWithGrid: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 30) {
                ForEach(items) { item in
                    VerticalCellView(item: item)
                }
            }
            .padding(.horizontal)
        }
    }
}

struct VerticalCellView: View {

    var item: WebAppModel

    private var randomNotificationBadge: some View {
        let notificationCount = (Int.random(in: 0...20))
        return Text(notificationCount > 10 ? "99+" : "\(notificationCount)")
            .font(.system(size: 12))
            .frame(width: 25, height: 25)
            .background(.red)
            .foregroundColor(.white)
            .clipShape(Circle())
    }

    var body: some View {
        VStack {
            Image(systemName: item.logo)
                .resizable()
                .scaledToFit()
                .background(.yellow.opacity(0.2))
                .overlay(alignment: .topTrailing) {
                    randomNotificationBadge
                }
            Text(item.name)
                .font(.headline)
        }
        .frame(height: 150)
    }
}

Portrait

Landscape

屏幕截图来自 iPad 10 代。

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