如何在swiftui中将一个视图绑定到另一个视图?
我有一个应用程序,我正在创建一个带有一系列楔子的圆,每个楔子都有一个类别标题,应该出现在楔子的顶部。我创建了楔子和一些弯曲的文本,这些文本应该位于圆的外边缘。然而,当我改变手机的大小时,文字会以不同的比例移动。 所以我的问题是,我如何将文本锚定到圆圈上,这样无论手机大小,它都会保持不变如何在swiftui中将一个视图绑定到另一个视图?,swiftui,Swiftui,我有一个应用程序,我正在创建一个带有一系列楔子的圆,每个楔子都有一个类别标题,应该出现在楔子的顶部。我创建了楔子和一些弯曲的文本,这些文本应该位于圆的外边缘。然而,当我改变手机的大小时,文字会以不同的比例移动。 所以我的问题是,我如何将文本锚定到圆圈上,这样无论手机大小,它都会保持不变 import SwiftUI struct WedgeShape: Shape { let startAngle: Angle let endAngle: Angle let lineW
import SwiftUI
struct WedgeShape: Shape {
let startAngle: Angle
let endAngle: Angle
let lineWidth: CGFloat
func path(in rect: CGRect) -> Path {
var p = Path()
let center = CGPoint(x: rect.size.width/2, y: rect.size.width/2)
let r1 = rect.size.width/2
p.addArc(center: center, radius: abs(lineWidth - r1), startAngle: startAngle, endAngle: endAngle, clockwise: false)
p.addArc(center: center, radius: r1, startAngle: endAngle, endAngle: startAngle, clockwise: true)
p.closeSubpath()
return p
}
}
struct Wedge {
var startAngle: Double
var endAngle: Double
var color: Color
var text: String
var offset: CGSize
var rotaion: Double
var radius: CGFloat
}
struct wedge: View {
@EnvironmentObject var assesmentClass: Assesments
let wedges = [
Wedge(startAngle: -90, endAngle: -45, color: Color.yellow, text: "Assess", offset: CGSize(width: -0.0, height: -15.0), rotaion: 25, radius: 135),
Wedge(startAngle: -45, endAngle: 0, color: Color.red, text: "Paddle Out",offset: CGSize(width: 0.0, height: -20.0), rotaion: 70, radius: 130),
Wedge(startAngle: 0, endAngle: 45, color: Color.green, text: "Position",offset: CGSize(width: 0.0, height: -10.0), rotaion: 110, radius: 135),
Wedge(startAngle: 45, endAngle: 90, color: Color.blue, text: "Catch",offset: CGSize(width: 0.0, height: -10.0), rotaion: 155, radius: 135),
Wedge(startAngle: 90, endAngle: 135, color: Color.gray, text: "Take Off",offset: CGSize(width: 0.0, height: -10.0), rotaion: 205, radius: 135),
Wedge(startAngle: 135, endAngle: 180, color: Color.yellow, text: "Pop Up",offset: CGSize(width: 5.0, height: -10.0), rotaion: 245, radius: 135),
Wedge(startAngle: 180, endAngle: 225, color: Color.green, text: "Speed",offset: CGSize(width: 5.0, height: -10.0), rotaion: 290, radius: 135),
Wedge(startAngle: 225, endAngle: -90, color: Color.gray, text: "Manouvers",offset: CGSize(width: 5.0, height: -35.0), rotaion: -25, radius: 135)
]
var body: some View {
ZStack {
ForEach(0 ..< wedges.count) {
WedgeShape(
startAngle: Angle(degrees: self.wedges[$0].startAngle),
endAngle: Angle(degrees: self.wedges[$0].endAngle),
lineWidth: 44
)
.foregroundColor(self.wedges[$0].color)
//PieSlice(pies: assesmentClass.makePies())
CurvedText(text: self.wedges[$0].text, radius: self.wedges[$0].radius, spacing: 2).kerning(1).offset(self.wedges[$0].offset).foregroundColor(.black).rotationEffect(Angle(degrees: self.wedges[$0].rotaion))
}.scaledToFit()
}
}
}
导入快捷界面
结构楔形形状:形状{
让星际缠结:角度
让endAngle:角度
让线宽:CGFloat
func路径(在rect:CGRect中)->path{
var p=Path()
设中心=CGPoint(x:rect.size.width/2,y:rect.size.width/2)
设r1=rect.size.width/2
p、 addArc(中心:中心,半径:绝对值(线宽-r1),星形缠结:星形缠结,端角:端角,顺时针:假)
p、 addArc(中心:中心,半径:r1,星形缠结:端角,端角:星形缠结,顺时针:真)
p、 closeSubpath()
返回p
}
}
结构楔{
var startAngle:双
var端角:双
颜色:颜色
变量文本:字符串
变量偏移量:CGSize
变量旋转:双
变量半径:CGFloat
}
结构楔块:视图{
@环境对象var assesmentClass:评估
让楔子=[
楔块(星形:-90,端角:-45,颜色:颜色。黄色,文本:“评估”,偏移量:CGSize(宽度:-0.0,高度:-15.0),旋转:25,半径:135),
楔块(星形:45,端角:0,颜色:彩色。红色,文本:“划出”,偏移量:CGSize(宽度:0.0,高度:-20.0),旋转:70,半径:130),
楔形(星形:0,端角:45,颜色:color.green,文本:“位置”,偏移量:CGSize(宽度:0.0,高度:-10.0),旋转:110,半径:135),
楔形(星形:45,端角:90,颜色:color.blue,文本:“Catch”,偏移量:CGSize(宽度:0.0,高度:-10.0),旋转:155,半径:135),
楔形(星形:90,端角:135,颜色:color.gray,文本:“起飞”,偏移量:CGSize(宽度:0.0,高度:-10.0),旋转:205,半径:135),
楔形(星形:135,端角:180,颜色:color.yellow,文本:“弹出”,偏移量:CGSize(宽度:5.0,高度:-10.0),旋转:245,半径:135),
楔形(星形:180,端角:225,颜色:color.green,文本:“速度”,偏移量:CGSize(宽度:5.0,高度:-10.0),旋转:290,半径:135),
楔块(星形:225,端角:-90,颜色:color.gray,文本:“操纵”,偏移量:CGSize(宽度:5.0,高度:-35.0),旋转:-25,半径:135)
]
var body:一些观点{
ZStack{
ForEach(0..<楔块计数){
楔形风帽(
星形缠结:角度(度:self.wedges[$0]。星形缠结),
endAngle:Angle(度:self.wedges[$0].endAngle),
线宽:44
)
.foregroundColor(self.wedges[$0].color)
//PieSlice(pies:assesmentClass.makePies())
CurvedText(文本:self.wedges[$0]。文本,半径:self.wedges[$0]。半径,间距:2)。紧排(1)。偏移(self.wedges[$0]。偏移)。前底色(.black)。旋转效果(角度(度:self.wedges[$0]。旋转))
}.scaledofit()
}
}
}
这是视图的代码,正如您所看到的,我使用了带有硬编码值的偏移量,我相信这就是问题所在,但我不确定如何获取动态值,以便动态更改
下面是曲线文本视图的代码
//
// CurvedText.swift
// ombe_surf
//
// Created by Joby Ingram-Dodd on 09/04/2021.
//
import SwiftUI
private struct TextViewSizeKey: PreferenceKey {
static var defaultValue: [CGSize] { [] }
static func reduce(value: inout [CGSize], nextValue: () -> [CGSize]) {
value.append(contentsOf: nextValue())
}
}
private struct PropagateSize<V: View>: View {
var content: () -> V
var body: some View {
content()
.background(GeometryReader { proxy in
Color.clear.preference(key: TextViewSizeKey.self, value: [proxy.size])
})
}
}
private struct IdentifiableCharacter: Identifiable {
var id: String { "\(index) \(character)" }
let index: Int
let character: Character
}
extension IdentifiableCharacter {
var string: String { "\(character)" }
}
extension Array {
subscript(safe index: Int) -> Element? {
indices.contains(index) ? self[index] : nil
}
}
// MARK: - Curved Text
public struct CurvedText: View {
public var text: String
public var radius: CGFloat
internal var textModifier: (Text) -> Text = { $0 }
internal var spacing: CGFloat = 0
@State private var sizes: [CGSize] = []
private func textRadius(at index: Int) -> CGFloat {
radius - size(at: index).height / 2
}
public var body: some View {
VStack {
ZStack {
ForEach(textAsCharacters()) { item in
PropagateSize {
self.textView(char: item)
}
.frame(width: self.size(at: item.index).width,
height: self.size(at: item.index).height)
.offset(x: 0,
y: -self.textRadius(at: item.index))
.rotationEffect(self.angle(at: item.index))
}
}
.frame(width: radius * 2, height: radius * 2)
.onPreferenceChange(TextViewSizeKey.self) { sizes in
self.sizes = sizes
}
}
.accessibility(label: Text(text))
}
private func textAsCharacters() -> [IdentifiableCharacter] {
let string = String(text.reversed())
return string.enumerated().map(IdentifiableCharacter.init)
}
private func textView(char: IdentifiableCharacter) -> some View {
textModifier(Text(char.string))
.rotationEffect(.degrees(180))
}
private func size(at index: Int) -> CGSize {
sizes[safe: index] ?? CGSize(width: 1000000, height: 0)
}
private func angle(at index: Int) -> Angle {
let arcSpacing = Double(spacing / radius)
let letterWidths = sizes.map { $0.width }
let prevWidth =
index < letterWidths.count ?
letterWidths.dropLast(letterWidths.count - index).reduce(0, +) :
0
let prevArcWidth = Double(prevWidth / radius)
let totalArcWidth = Double(letterWidths.reduce(0, +) / radius)
let prevArcSpacingWidth = arcSpacing * Double(index)
let arcSpacingOffset = -arcSpacing * Double(letterWidths.count - 1) / 2
let charWidth = letterWidths[safe: index] ?? 0
let charOffset = Double(charWidth / 2 / radius)
let arcCharCenteringOffset = -totalArcWidth / 2
let charArcOffset = prevArcWidth + charOffset + arcCharCenteringOffset + arcSpacingOffset + prevArcSpacingWidth
return Angle(radians: charArcOffset)
}
}
extension CurvedText {
public func kerning(_ kerning: CGFloat) -> CurvedText {
var copy = self
copy.spacing = kerning
return copy
}
public func italic() -> CurvedText {
var copy = self
copy.textModifier = {
self.textModifier($0)
.italic()
}
return copy
}
public func bold() -> CurvedText {
fontWeight(.bold)
}
public func fontWeight(_ weight: Font.Weight?) -> CurvedText {
var copy = self
copy.textModifier = {
self.textModifier($0)
.fontWeight(weight)
}
return copy
}
}
struct CurvedText_Previews: PreviewProvider {
static var previews: some View {
Group {
CurvedText(text: "Hello World!", radius: 200)
CurvedText(text: "Hello World!", radius: 100)
.kerning(5)
.italic()
.fontWeight(.heavy)
}
.previewLayout(.sizeThatFits)
}
}
//
//斯威夫特曲线
//ombe_冲浪
//
//由Joby Ingram Dodd于2021年4月9日创建。
//
导入快捷键
私有结构TextViewSizeKey:PreferenceKey{
静态变量defaultValue:[CGSize]{[]}
静态函数缩减(值:inout[CGSize],nextValue:()->[CGSize]){
append(contentsOf:nextValue())
}
}
私有结构大小:视图{
var内容:()->V
var body:一些观点{
内容()
.background(GeometryReader{proxy in
Color.clear.preference(键:TextViewSizeKey.self,值:[proxy.size])
})
}
}
私有结构可识别字符:可识别{
变量id:字符串{“\(索引)\(字符)”}
let索引:Int
让角色:角色
}
扩展可识别字符{
变量字符串:字符串{“\(字符)”}
}
扩展阵列{
下标(安全索引:Int)->元素{
索引。包含(索引)?自[索引]:无
}
}
//标记:-曲线文本
公共结构曲线文本:视图{
公共变量文本:字符串
公共变量半径:CGFloat
内部变量textModifier:(Text)->Text={$0}
内部变量间距:CGFloat=0
@国家私有变量大小:[CGSize]=[]
私有函数textRadius(在索引处:Int)->CGFloat{
半径-大小(在:索引处)。高度/2
}
公共机构:一些看法{
VStack{
ZStack{
ForEach(textAsCharacters()){item in
传播大小{
self.textView(字符:项)
}
.frame(宽度:self.size(at:item.index)。宽度,
高度:self.size(at:item.index.height)
.偏移量(x:0,
y:-self.textRadius(at:item.index))
.旋转效应(自身角度(at:项目索引))
}
}
.框架(宽度:半径*2,高度:半径*2)
.onPreferenceChange(TextViewSizeKey.self){中的大小
self.size=大小
}
}
.可访问性(标签:文本)
}
private func textAsCharacters()->[可识别字符]{
let string=string(text.reversed())
返回字符串.enumerated().map(IdentifiableCharacter.init)
}
私有func文本视图(字符:可识别字符)->某些视图{
textModifier(文本(char.string))