SwiftUI:在列表中的两个视图之间画一条线/如何确定视图的中心位置?
SwiftUI: Drawing a line between two views in a list / how to determine the center location of a view?
我想在按下“连接”按钮时在选定的源视图和选定的目标视图之间画一条线。
据我了解,我需要这些视图的(中心?)CGPoint ...
如何确定 forEach-HStack-list 中视图的中心 CGPoint?
两个列表中的元素将是 removed/added。
struct ContentView: View {
@State private var selectedTarget: Int = 0
@State private var selectedSource: Int = 3
@State private var isConnected = false
var body: some View {
ZStack {
VStack {
HStack {
ForEach(0..<6) { index in
Text("Target \(index)")
.padding()
.foregroundColor(.white)
.background(selectedTarget == index ? .red : .black)
.onTapGesture {
selectedTarget = index
}
}
}
List {
EmptyView()
}
.frame(width: 400, height: 400, alignment: .center)
.border(.black, width: 2)
HStack {
ForEach(0..<6) { index in
Text("Source \(index)")
.padding()
.foregroundColor(.white)
.background(selectedSource == index ? .orange : .black)
.onTapGesture {
selectedSource = index
}
}
}
Button(isConnected ? "CUT" : "CONNECT") {
isConnected.toggle()
}
.padding()
}
}
}
}
这是粗略的演示代码,并从这段代码中汲取灵感。
您可以通过首先通过 GeometryReader
找到 Text
的位置并绘制这些点之间的路径来实现此目的。
struct ContentView: View {
@State private var selectedTarget: Int = 0
@State private var selectedSource: Int = 3
@State private var isConnected = false
@State private var targetCGPoint: CGPoint = .zero
@State private var sourceCGPoint: CGPoint = .zero
var body: some View {
ZStack {
if isConnected {
getPath()
}
VStack {
HStack {
ForEach(0..<6) { index in
GeometryReader { geo in
Text("Target \(index)")
.padding()
.foregroundColor(.white)
.background(selectedTarget == index ? Color.red : Color.black)
.onTapGesture {
let size = geo.size
targetCGPoint = CGPoint(x: geo.frame(in: .global).origin.x + (size.width / 2), y: geo.frame(in: .global).origin.y)
print("Target Global center: \(geo.frame(in: .global).midX) x \(geo.frame(in: .global).midY)")
selectedTarget = index
}
}
}
}
// Removed list for demo
Spacer()
HStack {
ForEach(0..<6) { index in
GeometryReader { geo in
Text("Source \(index)")
.padding()
.foregroundColor(.white)
.background(selectedSource == index ? Color.orange : Color.black)
.onTapGesture {
let size = geo.size
sourceCGPoint = CGPoint(x: geo.frame(in: .global).origin.x + (size.width / 2), y: geo.frame(in: .global).origin.y)
print("Source Global center: \(geo.frame(in: .global).midX) x \(geo.frame(in: .global).midY)")
selectedSource = index
}
}
}
}
Button(isConnected ? "CUT" : "CONNECT") {
isConnected.toggle()
}
.padding()
}
}
}
func getPath() -> some View {
Path { path in
path.move(to: sourceCGPoint)
path.addLine(to: targetCGPoint)
}
.stroke(Color.blue, lineWidth: 10)
}
}
我想在按下“连接”按钮时在选定的源视图和选定的目标视图之间画一条线。 据我了解,我需要这些视图的(中心?)CGPoint ... 如何确定 forEach-HStack-list 中视图的中心 CGPoint?
两个列表中的元素将是 removed/added。
struct ContentView: View {
@State private var selectedTarget: Int = 0
@State private var selectedSource: Int = 3
@State private var isConnected = false
var body: some View {
ZStack {
VStack {
HStack {
ForEach(0..<6) { index in
Text("Target \(index)")
.padding()
.foregroundColor(.white)
.background(selectedTarget == index ? .red : .black)
.onTapGesture {
selectedTarget = index
}
}
}
List {
EmptyView()
}
.frame(width: 400, height: 400, alignment: .center)
.border(.black, width: 2)
HStack {
ForEach(0..<6) { index in
Text("Source \(index)")
.padding()
.foregroundColor(.white)
.background(selectedSource == index ? .orange : .black)
.onTapGesture {
selectedSource = index
}
}
}
Button(isConnected ? "CUT" : "CONNECT") {
isConnected.toggle()
}
.padding()
}
}
}
}
这是粗略的演示代码,并从这段代码中汲取灵感。
您可以通过首先通过 GeometryReader
找到 Text
的位置并绘制这些点之间的路径来实现此目的。
struct ContentView: View {
@State private var selectedTarget: Int = 0
@State private var selectedSource: Int = 3
@State private var isConnected = false
@State private var targetCGPoint: CGPoint = .zero
@State private var sourceCGPoint: CGPoint = .zero
var body: some View {
ZStack {
if isConnected {
getPath()
}
VStack {
HStack {
ForEach(0..<6) { index in
GeometryReader { geo in
Text("Target \(index)")
.padding()
.foregroundColor(.white)
.background(selectedTarget == index ? Color.red : Color.black)
.onTapGesture {
let size = geo.size
targetCGPoint = CGPoint(x: geo.frame(in: .global).origin.x + (size.width / 2), y: geo.frame(in: .global).origin.y)
print("Target Global center: \(geo.frame(in: .global).midX) x \(geo.frame(in: .global).midY)")
selectedTarget = index
}
}
}
}
// Removed list for demo
Spacer()
HStack {
ForEach(0..<6) { index in
GeometryReader { geo in
Text("Source \(index)")
.padding()
.foregroundColor(.white)
.background(selectedSource == index ? Color.orange : Color.black)
.onTapGesture {
let size = geo.size
sourceCGPoint = CGPoint(x: geo.frame(in: .global).origin.x + (size.width / 2), y: geo.frame(in: .global).origin.y)
print("Source Global center: \(geo.frame(in: .global).midX) x \(geo.frame(in: .global).midY)")
selectedSource = index
}
}
}
}
Button(isConnected ? "CUT" : "CONNECT") {
isConnected.toggle()
}
.padding()
}
}
}
func getPath() -> some View {
Path { path in
path.move(to: sourceCGPoint)
path.addLine(to: targetCGPoint)
}
.stroke(Color.blue, lineWidth: 10)
}
}