【问题标题】:How to extend tappable area to whole frame in SwiftUI (iOS14)?如何在 SwiftUI (iOS14) 中将可点击区域扩展到整个框架?
【发布时间】:2020-10-22 08:16:58
【问题描述】:

我正在尝试使用 Swift 5.3 制作 VGrid,但唯一可点击的区域是矩形的上部。其他答案建议contentShape,但我也无法完成这项工作。如何使整个框架可点击?代码如下:

import SwiftUI
import Combine
import Foundation

struct Item: Codable, Identifiable, Equatable {
    var id: Int
    var name: String
}

final class UserData: ObservableObject {
    @Published var items = Bundle.main.decode([Item].self, from: "data.json")
}

struct ContentView: View {
    @State var itemID = Item.ID()
    @StateObject var userData = UserData()
    let columns = [
        GridItem(.adaptive(minimum: 118))
    ]

    var body: some View {
        NavigationView {
            ScrollView {
                LazyVGrid(columns: columns) {
                    ForEach(userData.items) { item in
                        NavigationLink(destination: ContentDetail(itemID: item.id - 1)) {
                            ContentRow(item: item)
                        }
                    }
                }
            }
        }
    }
}

struct ContentRow: View {
    var item: Item
    
    var body: some View {
        VStack {
            GeometryReader { geo in
                ZStack{
                    VStack(alignment: .trailing) {
                        Text(item.name)
                            .font(.caption)
                    }
                }
                .padding()
                .foregroundColor(Color.primary)
                .frame(width: geo.size.width, height: 120)
                .border(Color.primary, width: 2)
                .cornerRadius(5)
                .contentShape(Rectangle())
            }
        }
    }
}

struct ContentDetail: View {
    @State var itemID = Item.ID()
    @StateObject var userData = UserData()

    var body: some View {
            Text(userData.items[itemID].name)
    }
}

extension Bundle {
    func decode<T: Decodable>(_ type: T.Type, from file: String, dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate, keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) -> T {
        guard let url = self.url(forResource: file, withExtension: nil) else {
            fatalError("Failed to locate \(file) in bundle.")
        }

        guard let data = try? Data(contentsOf: url) else {
            fatalError("Failed to load \(file) from bundle.")
        }

        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = dateDecodingStrategy
        decoder.keyDecodingStrategy = keyDecodingStrategy

        do {
            return try decoder.decode(T.self, from: data)
        } catch DecodingError.keyNotFound(let key, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing key '\(key.stringValue)' not found – \(context.debugDescription)")
        } catch DecodingError.typeMismatch(_, let context) {
            fatalError("Failed to decode \(file) from bundle due to type mismatch – \(context.debugDescription)")
        } catch DecodingError.valueNotFound(let type, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing \(type) value – \(context.debugDescription)")
        } catch DecodingError.dataCorrupted(_) {
            fatalError("Failed to decode \(file) from bundle because it appears to be invalid JSON")
        } catch {
            fatalError("Failed to decode \(file) from bundle: \(error.localizedDescription)")
        }
    }
}

还有 JSON 部分:

[
    {
        "id": 1,
        "name": "Example data",
    },
    {
        "id": 2,
        "name": "Example data 2",
    }
]

感谢任何帮助。这可能是 SwiftUI 中的错误吗?

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    尝试将 contentShape 放在 ContentRow 的最外层 VStack 上。您需要将 contentShape 放在 expanding 的视图上以填充其父级(或其父级),在您的情况下,我认为是 GeometryReader。 GeometryReader 中的视图都会缩小以适应它们的内容,因此您的 contentShape 矩形在这方面无济于事。

    【讨论】:

      【解决方案2】:

      您可以简单地删除 GeometryReader,因为您仍然设置了高度:

      struct ContentRow: View {
          var item: Item
          
          var body: some View {
              VStack {
                  ZStack{
                      VStack(alignment: .trailing) {
                          Text(item.name)
                              .font(.caption)
                      }
                  }
                  .padding()
                  .foregroundColor(Color.primary)
                  .frame(width: 120, height: 120)
                  .border(Color.primary, width: 2)
                  .cornerRadius(5)
                  .background(Color.red)
              }
          }
      }
      

      【讨论】:

      • 我最终只设置了高度,我猜网格视图会处理宽度。这是 GeometryReader 错误吗?
      猜你喜欢
      • 2020-09-06
      • 2012-11-15
      • 2023-03-09
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多