如何解决SwiftUI-水平扩展主网格将我的其他视图推离屏幕
我正在使用SwiftUI开发iPhone应用程序。主网格使用嵌套在VStack中的HStack。列数在初始化时是可变的,但此后固定。行数是完全动态的。当网格扩展到超出屏幕的宽度或高度时,它将其他视图推开。
我希望它向右(在初始化时)和向下(动态)在屏幕外以及其他视图后面扩展。我尝试将所有内容放入ZStack并设置其zindice,但这没有用。有什么办法可以做到?还是我需要一种新的方法?
//
// GameView.swift
// Scoreboard
//
// Created by user926153 on 8/21/20.
// Copyright © 2020 user926153. All rights reserved.
//
//
//
/*
This uses the TrackableScrollView as created by Max Natchanon here:
https://medium.com/@maxnatchanon/swiftui-how-to-get-content-offset-from-scrollview-5ce1f84603ec
*/
import SwiftUI
import UIKit
struct ScrollOffsetPreferenceKey: PreferenceKey {
typealias Value = [CGFloat]
static var defaultValue: [CGFloat] = [0]
static func reduce(value: inout [CGFloat],nextValue: () -> [CGFloat]) {
value.append(contentsOf: nextValue())
}
}
struct TrackableScrollView<Content>: View where Content: View {
let axes: Axis.Set
let showIndicators: Bool
@Binding var contentOffset: CGFloat
let content: Content
init(_ axes: Axis.Set = .vertical,showIndicators: Bool = true,contentOffset: Binding<CGFloat>,@ViewBuilder content: () -> Content) {
self.axes = axes
self.showIndicators = showIndicators
self._contentOffset = contentOffset
self.content = content()
}
var body: some View {
GeometryReader { outsideProxy in
ScrollView(self.axes,showsIndicators: self.showIndicators) {
ZStack(alignment: self.axes == .vertical ? .top : .leading) {
GeometryReader { insideProxy in
Color.clear
.preference(key: ScrollOffsetPreferenceKey.self,value: [self.calculateContentOffset(fromOutsideProxy: outsideProxy,insideProxy: insideProxy)])
// Send value to the parent
}
VStack {
self.content
}
}
}
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
self.contentOffset = value[0]
}
// Get the value then assign to offset binding
}
}
private func calculateContentOffset(fromOutsideProxy outsideProxy: GeometryProxy,insideProxy: GeometryProxy) -> CGFloat {
if axes == .vertical {
return (outsideProxy.frame(in: .global).minY - insideProxy.frame(in: .global).minY) * -1
} else {
return (outsideProxy.frame(in: .global).minX - insideProxy.frame(in: .global).minX) * -1
}
}
}
struct GameView: View {
let row_label_offset: CGFloat = 80
let col_width: CGFloat = 75
let row_height: CGFloat = 50
@ObservedObject var settings: GameSettings
@State var round_number: Int = 1
@State var scores: [[Int]] = [[0,0]]
@State var column_offset: CGFloat = 0
@State var row_offset: CGFloat = 0
private func AddRound() {
self.round_number += 1
self.scores.append([0,0])
}
private func DeleteRound(at offsets: IndexSet) {
// NOTE: also have to delete round from score array
self.round_number -= 1
self.scores.remove(atOffsets: offsets)
}
var body: some View {
VStack {
VStack(alignment: .center,spacing: 10) {
Text("Title")
.font(.title)
Text("subtitle")
}
.border(Color.black)
VStack(alignment: .leading,spacing: 10) {
HStack {
Button(action: {
self.AddRound()
}) {
Text("New round +")
.fixedSize(horizontal: false,vertical: true)
}
.frame(width: self.row_label_offset,height: self.row_height)
TrackableScrollView(.horizontal,showIndicators: false,contentOffset: $column_offset) {
HStack {
ForEach((1...7),id: \.self) {
Text("Player \($0)\n total")
.frame(width: self.col_width,height: self.row_height)
}
}
}
.frame(height: 50)
.border(Color.red)
}
HStack {
TrackableScrollView(.vertical,contentOffset: $row_offset) {
ForEach((1...self.round_number),id: \.self) { round in
Text("Round \(round)")
.frame(width: self.col_width,height: self.row_height)
}
}
.border(Color.black)
.frame(width: self.row_label_offset)
VStack {
ForEach(self.scores,id: \.self) { round_score in
HStack {
ForEach(round_score,id: \.self) { score in
Text("\(score)")
.frame(width: self.col_width,height: self.row_height)
}
}
}
Spacer()
}
.offset(x: self.column_offset,y: self.row_offset)
Spacer()
}
.border(Color.blue)
}
Button(action: {
}) {
Text("Finish Game")
}
Spacer()
}
}
}
#if DEBUG
struct GameView_Previews: PreviewProvider {
static var previews: some View {
GameView(settings: GameSettings())
}
}
#endif
解决方法
这是固定的零件-为避免布局损坏,您必须将动态零件移出当前布局,例如。在空白区域的叠加中。还添加了一些较小的修复程序,例如剪切和对齐。
通过Xcode 12 / iOS 14测试
HStack {
TrackableScrollView(.vertical,showIndicators: false,contentOffset: $row_offset) {
ForEach((1...self.round_number),id: \.self) { round in
Text("Round \(round)")
.frame(width: self.col_width,height: self.row_height)
}
}
.border(Color.black)
.frame(width: self.row_label_offset)
Color.clear.overlay ( // << from here !!
VStack {
ForEach(self.scores,id: \.self) { round_score in
HStack {
ForEach(round_score,id: \.self) { score in
Text("\(score)")
.frame(width: self.col_width,height: self.row_height)
}
}
}
Spacer()
}
.offset(x: self.column_offset,y: self.row_offset),alignment: .topLeading)
.clipped()
}
.border(Color.blue)
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。