我的应用程序使用 GeometryReader 和一些填充来设置 NavigationView 内的视图框架尺寸。
从 iOS 14 开始,我收到以下错误消息:
无效的框架尺寸(负或非有限)
下面是一些要测试的示例代码:
import SwiftUI
struct ContentView: View {
let padding:CGFloat = 16.0
var body: some View {
NavigationView {
GeometryReader { p in
Text("Hello, world!")
.frame(width: p.size.width - padding)
.padding()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Run Code Online (Sandbox Code Playgroud)
删除 NavigationView 解决了这个问题,但我需要 NavigationView 中容器视图的当前宽度和高度。
有什么建议吗?
我有一个自定义视图:
struct ImageContent: View {
var body: some View {
Image("smile")
.resizable()
.scaledToFit()
}
}
Run Code Online (Sandbox Code Playgroud)
哪个被放置到另一个视图中GeometryReader:
var body: some View {
GeometryReader { geometry in
ImageContent()
//Image("smile").resizable().scaledToFit()
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,ImageContent视图不是在屏幕上居中,而是被放置在顶部,但是,通过删除ImageContent子视图并将视图的内容直接添加到几何阅读器中将解决这个问题(见图)。
此外,删除GeometryReader也可以解决问题。
我需要子视图,因为我将实现一些额外的逻辑,还需要 ,GeometryReader因为有一个手势添加到Image使用它的 。
任何的想法?
我经常遇到这样的情况:我想要缩放图像,以便它按比例填充其容器而不修改其框架。下面的第一个屏幕截图中显示了一个示例。容器视图具有固定框架,如红色边框所示。图像本身具有不同的长宽比。它被缩放以填充整个容器,但它仍然具有与容器相同的框架,因此不会影响容器的布局(大小)。
我使用以下代码来完成此操作:
struct ContentView: View {
var body: some View {
ImageContainerView()
.frame(width: 300, height: 140)
.border(.red, width: 2)
}
}
struct ImageContainerView: View {
var body: some View {
GeometryReader { geometry in
Image("image")
.resizable()
.aspectRatio(contentMode: .fill)
.border(.blue, width: 2)
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
}
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我使用几何读取器手动设置图像的框架以匹配父视图的框架。这感觉有点多余,因为图像已经从其父视图隐式接收到此信息作为建议的大小。但是,如果我不以这种方式使用几何读取器,则图像不会被剪切,并且其框架与完整缩放的图像匹配,而不是父视图的框架。下面的第二个屏幕截图显示了这一点。
SwiftUI 中是否有一种(更“原生”)的方法可以在不使用几何读取器的情况下实现所需的行为?
如何在 GeometryReader 中设置 @State var?
这是我的代码:
@State var isTest:Int = 0
var body: some View {
VStack{
ForEach(self.test, id: \.id) { Test in
VStack{
GeometryReader { geometry in
self.isTest = 1
Run Code Online (Sandbox Code Playgroud)
我尝试使用一个函数,但它不起作用。
@State var isTest: Int = 0
func testValue() {
self.isTest = 1
}
var body: some View {
VStack{
ForEach(self.test, id: \.id) { Test in
VStack{
GeometryReader { geometry in
testValue()
Run Code Online (Sandbox Code Playgroud)
任何想法?谢谢!
我想使用 GeometryReader 来使用一些计算。没有我的设计看起来应该:
var body: some View {
ZStack {
Color(#colorLiteral(red: 0.117543973, green: 0.2897527516, blue: 0.4028342962, alpha: 1)).edgesIgnoringSafeArea(.all)
VStack {
HStack(spacing: self.spacing) { // todo auch berechnen?
ForEach(self.chartValues, id: \.self) { point in
DataPoint(width: 200)
}
}.animation(.default)
}
}
}
Run Code Online (Sandbox Code Playgroud)
添加后,每条线的高度都相互重叠,我做错了什么:
var body: some View {
ZStack {
Color(#colorLiteral(red: 0.117543973, green: 0.2897527516, blue: 0.4028342962, alpha: 1)).edgesIgnoringSafeArea(.all)
VStack {
GeometryReader { geo in
HStack(spacing: self.spacing) { // todo auch berechnen?
ForEach(self.chartValues, id: \.self) { point in
DataPoint(width: geo.size.width)
}
}.animation(.default)
} …Run Code Online (Sandbox Code Playgroud) 这可能是一个简单的情况,但我找不到解决方案。
\n\n这是我的代码,使用 GeometryReader 设置 SwiftUI 视图大小的相对布局,如图像。问题出现在最后一个VStack上,我希望文本的背景转到VStack的右端。因此,我将其设置为,Text("Haibo: asdasd").frame(maxWidth: .infinity)但之后我发现文本变为水平居中并且不遵循 VStack 对齐方式:.leading。
import SwiftUI\n\nstruct ContentView: View {\n var body: some View {\n\n GeometryReader { geo in\n HStack(alignment: .top, spacing: 12) {\n Image("Alan shore").resizable().frame(width: geo.size.width / 6, height: geo.size.width / 6).cornerRadius(4)\n\n VStack(alignment: .leading, spacing: 10) {\n\n // name\n Text("Haibo")\n // content\n Text("Think ThinkThink ThinkThink ThinkThink ThinkThink ThinkThink ThinkThink ThinkThink Think")\n // \xe4\xb9\x9d\xe5\xae\xab\xe6\xa0\xbc\n VStack(spacing: 6) {\n\n HStack(spacing: 6) {\n Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)\n Image("Little …Run Code Online (Sandbox Code Playgroud) 因此,我一段时间以来一直在尝试找出如何在 SwiftUI 中查找图像的高度,但没有成功。本质上,我有纵向/横向图像,我想要以大约 600 pt 高显示纵向图像,而我想要显示横向图像,因此使用图像的宽度,因此高度是任意的。话虽这么说,我希望它位于 GeometryReader 内部,因为我使用的偏移量使用它,这样当您向下滚动时,图像不会滚动,但如果您向上滚动,它就会滚动。我不相信我可以共享图像,但无论如何,这应该足以成功运行它!
struct ContentView: View {
@Environment(\.presentationMode) var mode: Binding<PresentationMode>
var backButton: some View {
Button(action: {
withAnimation {
self.mode.wrappedValue.dismiss()
}
}) {
Image(systemName: "chevron.left.circle.fill")
.opacity(0.8)
.font(.system(size: 30))
.foregroundColor(.black)
.background(Color.gray.mask(Image(systemName: "chevron.left").offset(x: 9.4, y: 7.6)))
}
}
var body: some View {
ScrollView(showsIndicators: false) {
GeometryReader { geometry in
Image("image1")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: UIScreen.main.bounds.width, minHeight: 350, maxHeight: 600, alignment: .top)
.clipped()
.overlay(
Rectangle()
.foregroundColor(.clear)
.background(LinearGradient(gradient: Gradient(colors: [.clear, .white]), startPoint: .center, endPoint: .bottom))
)
.offset(y: …Run Code Online (Sandbox Code Playgroud) 这是我的例子,我无法判断这是否是一个错误。我的所有单元格都正确加载,但是当我尝试将其作为工作表打开时DetailView(),传入的项目始终是网格中首先显示的项目(在我的情况下位于左上角),而不是原来的“单元格”被点击。那么,为什么 ForEach 循环中的项目正确填充单元格,但没有通过按钮传递到 .sheet ?
import SwiftUI
let columnCount: Int = 11
let gridSpacing: CGFloat = 1
struct GridView: View {
@State var showingDetail = false
let data = (1...755).map { "\($0)" }
let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: gridSpacing), count: columnCount)
let colCount: CGFloat = CGFloat(columnCount)
var body: some View {
GeometryReader { geo in
ScrollView (showsIndicators: false) {
LazyVGrid(columns: columns, spacing: gridSpacing) {
ForEach(data, id: \.self) { item in
Button(action: {
self.showingDetail.toggle()
}) {
GridCell(item: …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 SwiftUI 在我的应用程序中实现拖放功能。
我创建了两个圆圈,它们位于两个不同的HStacks. 它们不共享相同的坐标空间。
带有描边的圆圈是目标,绿色实心圆圈是要拖动的对象。
我能够使用GeometryReaderinside an来获得他们的绝对位置.overlay。我用它来检测当对象圆被拖动到目标圆上时它们是否重叠。这有效。
当它们不重叠时,对象圆将移回其原始位置。当它们重叠时,对象圆应该卡入目标圆的位置。这是我似乎有问题的地方。
我试图通过以下方式设置对象圆的新 X 和 Y 位置:对象圆本地位置 - 对象圆全局位置 + 目标圆全局位置。
objectPosition = CGPoint(
x: objectPosition.x - objectFrame.midX + targetFrame.midX,
y: objectPosition.y - objectFrame.midY + targetFrame.midY
)
Run Code Online (Sandbox Code Playgroud)
我假设这会将我带到目标圆的坐标空间。但不知怎的,它不起作用。
到目前为止,我一直无法找到一种可靠且简单的方法来转换 SwiftUI 中的坐标空间。使用覆盖内部的解决方法GeometryReader至少给了我正确的全局位置。但我还没有找到一种方法来使用这些位置将视图放置在.global坐标空间中。
如果有人知道为什么我对坐标空间的计算是错误的,或者甚至知道一种更容易地相对于彼此转换和定位视图的方法,我将非常感激。
这是我的 SwiftUI 单视图 iOS 应用程序的代码:
import SwiftUI
struct ContentView: View {
@State private var isDragging: Bool = false
@State private var objectDragOffset: CGSize = .zero
@State private var objectPosition: CGPoint = …Run Code Online (Sandbox Code Playgroud) 挑战:我想跟踪 ScrollView 的哪个子视图位于该 ScrollView 可见区域的中间。
问题:据我了解,没有原生 SwiftUI 方法可以确定 ScrollView 的子视图当前在屏幕上是否可见。或者我想念这里的什么吗?
我的解决方案:我使用 PreferenceKey 来收集子视图位置,并在 ScrollView 滚动时连续发生的 PreferenceChange 上执行操作:检查最接近屏幕中心的视图。
问题:基于 PreferenceKey 的解决方案适用于一些子视图。但我需要跟踪最多 3000 个子视图(从数据库构建的大型结构化文档的视图)。即使在实施了我能够提出的一些优化之后,大量视图的性能也是不可接受的。
我的问题是:有吗
(iOS 14.4 / Xcode 12.4)
private struct ViewOffsetsKey: PreferenceKey {
static var defaultValue: [Int: CGFloat] = [:]
static func reduce(value: inout [Int: CGFloat], nextValue: () -> [Int: CGFloat]) {
value.merge(nextValue(), uniquingKeysWith: { $1 })
}
}
struct ContentView: View {
@State private var offsets: [Int: CGFloat] = [:]
@State private var …Run Code Online (Sandbox Code Playgroud) geometryreader ×10
swiftui ×10
swift ×3
image ×2
ios ×2
aspect-ratio ×1
clipping ×1
coordinates ×1
ios14 ×1
layout ×1
lazyvgrid ×1
popover ×1
position ×1
scroll ×1
scrollview ×1