Upgrade to Pro — share decks privately, control downloads, hide ads and more …

入門 SwiftUI Alignment Guide / iOSDC2022

monoqlo
September 11, 2022

入門 SwiftUI Alignment Guide / iOSDC2022

iOSDC Japan 2022 2022/09/11

monoqlo

September 11, 2022
Tweet

More Decks by monoqlo

Other Decks in Technology

Transcript

  1. @monoqloʢ΋ͷ͘Ζʣ ೖ໳SwiftUI Alignment Guide iOSDC Japan 2022

  2. ͸͡Ίʹ

  3. • ʮೖ໳ʯͱ͋ΔΑ͏ʹϝΠϯλʔήοτ͸SwiftUIॳ৺ऀͰ͢ • ۩ମతʹ͸ŋŋŋ • alignmentGuide(_:computeValue:) ࢖ͬͨ͜ͱͳ͍ • Custom Alignment

    Guide࢖ͬͨ͜ͱͳ͍ • ࢖ͬͨ͜ͱ͋Δ͚ͲΑ͘Θ͔Βͳ͔ͬͨ ॳ৺ऀ޲͚ͷτʔΫͰ͢
  4. • 2,3೥લ͸͔ͬ͢Β͔ΜͩͬͨެࣜυΩϡϝϯτ… • ͍ͭͷ·ʹ͔େॆ࣮ • ࠷ֶۙͼ࢝Ίͨਓ͸ٯʹΑ͘஌͍ͬͯΔՄೳੑ😇 • ਖ਼௚͜ͷτʔΫͷඞཁੑΛٙ͏΄ͲΊͪΌͪ͘Όྑ͍ࢿྉ • ͔͍ͭ·ΜͰҾ༻ͭͭ͠ղઆ

    • εϥΠυͷ࠷ޙʹࢀߟจݙͱͯ͠URLهࡌ ࠷ۙͷެࣜυΩϡϝϯτ͸େॆ࣮
  5. ୈষ Alignment Guideͱ͸

  6. ྫ୊

  7. HStack { VStack { Rectangle() .fill(.blue) .frame(width: 100, height: 400)

    Text("Long Blue Bar") .font(.title) } VStack { Rectangle() .fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar") .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } }
  8. None
  9. ղ౴ྫ

  10. HStack { VStack { Rectangle() .fill(.blue) .frame(width: 100, height: 400)

    Text("Long Blue Bar") .font(.title) } VStack { Rectangle() .fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar") .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } }
  11. HStack(alignment: .bottom) { VStack { Rectangle() .fill(.blue) .frame(width: 100, height:

    400) Text("Long Blue Bar") .font(.title) } VStack { Rectangle() .fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar") .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } }
  12. ղઆ

  13. VStack { Text("Hello,") Text("😺🐶🐢🐰🐳") Text("Animals!") }

  14. VStack { Text("Hello,") Text("😺🐶🐢🐰🐳") Text("Animals!") }

  15. VStack { Color.white.frame(width: 1) Text("Hello,") Text("😺🐶🐢🐰🐳") Text(“Animals!") Color.white.frame(width: 1) }

  16. VStack(alignment: .center) { Color.white.frame(width: 1) Text("Hello,") Text("😺🐶🐢🐰🐳") Text(“Animals!") Color.white.frame(width: 1)

    }
  17. VStack(alignment: .leading) { Color.white.frame(width: 1) Text("Hello,") Text("😺🐶🐢🐰🐳") Text(“Animals!") Color.white.frame(width: 1)

    }
  18. VStack(alignment: .leading) { Color.white.frame(width: 1) Text("Hello,") Text("😺🐶🐢🐰🐳") Text(“Animals!") Color.white.frame(width: 1)

    } .environment(\.layoutDirection, .rightToLeft)
  19. Built-in Alignment Guides

  20. HorizontalAlignment • leading • center • trailing • listRowSeparatorLeading •

    listRowSeparatorTrailing Built-in Alignment Guides VerticalAlignment • top • center • bottom • fi rstTextBaseline • lastTextBaseline
  21. HorizontalAlignment • leading • center • trailing • (listRowSeparatorLeading) •

    (listRowSeparatorTrailing) Built-in Alignment Guides
  22. VerticalAlignment • top • center • bottom • fi rstTextBaseline

    • lastTextBaseline Built-in Alignment Guides
  23. Alignment HorizontalAlignment × VerticalAlignment Built-in Alignment Guides https://developer.apple.com/documentation/swiftui/alignment

  24. Built-in Alignment Guides

  25. Custom Alignment Guide

  26. ୈষ alignmentGuide(_:computeValue:)

  27. ྫ୊

  28. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } Color.white.frame(width: 1) }
  29. None
  30. None
  31. ղ౴ྫ

  32. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", “Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } Color.white.frame(width: 1) }
  33. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Color.white.frame(width: 1) }
  34. ղઆ

  35. alignmentGuide(_:computeValue:)

  36. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) func alignmentGuide( _ g: VerticalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat ) -> some View https://developer.apple.com/documentation/swiftui/view/alignmentguide(_:computevalue:)-6y3u2 https://developer.apple.com/documentation/swiftui/view/alignmentguide(_:computevalue:)-9mdoh
  37. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ج४ͱͳΔAlignment͔ΒͷҐஔΛௐ੔Ͱ͖ΔViewModi fi er
  38. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ج४ͱͳΔAlignment͔ΒͷҐஔΛௐ੔Ͱ͖ΔViewModi fi er • ୈ1Ҿ਺͕ج४ͱͳΔAlignment e.g. VStack(alignment: .leading) ͷதʹೖ͍ͬͯΔViewΛௐ੔ ͍ͨ͠ͳΒ .leading Λࢦఆ
  39. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Color.white.frame(width: 1) }
  40. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Color.white.frame(width: 1) }
  41. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Circle() .fill(Color.green) .frame(width: 50, height: 50) Color.white.frame(width: 1) }
  42. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔͢Δ஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢
  43. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔͢Δ஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢ • Ҿ਺ͷViewDimensions͔Βར༻Ͱ͖Δ΋ͷ
  44. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔͢Δ஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢ • Ҿ਺ͷViewDimensions͔Βར༻Ͱ͖Δ΋ͷ • Viewͷwidth, height • ֤Alignment GuideҐஔʢoffset஋ʣ
  45. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔͢Δ஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢ • Ҿ਺ͷViewDimensions͔Βར༻Ͱ͖Δ΋ͷ • Viewͷwidth, height • ֤Alignment GuideҐஔʢoffset஋ʣ
  46. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔͢Δ஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢ • Ҿ਺ͷViewDimensions͔Βར༻Ͱ͖Δ΋ͷ • Viewͷwidth, height • ֤Alignment GuideҐஔʢoffset஋ʣ
  47. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } Color.white.frame(width: 1) }
  48. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } Color.white.frame(width: 1) }
  49. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Color.white.frame(width: 1) }
  50. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Color.white.frame(width: 1) }
  51. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Color.white.frame(width: 1) } 🤔* 2ʁ
  52. 🤔* 2ʁ

  53. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔͢Δ஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢
  54. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔͢Δ஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢ طଘ஋ͷ୅ΘΓʹ
  55. ϓϨʔϯͳঢ়ଶ == 0 VStack(alignment: .trailing) ˞Πϝʔδ

  56. .trailingͷσϑΥϧτ஋ ϓϨʔϯͳঢ়ଶ == 0 VStack(alignment: .trailing) ˞Πϝʔδ

  57. .trailingͷσϑΥϧτ஋ .alignmentGuide(.trailing) { context in context.width * 2 }

  58. .trailingͷσϑΥϧτ஋ .alignmentGuide(.trailing) { context in context.width * 2 } طଘ஋Λஔ͖׵͑Δ

  59. .trailingͷσϑΥϧτ஋ .alignmentGuide(.trailing) { context in context.width * 2 } طଘ஋Λஔ͖׵͑Δ

    .trailingͷσϑΥϧτ஋ ͷҐஔ͔Β Ҡಈ͢Δ༁Ͱ͸ͳ͍
  60. ϓϨʔϯͳঢ়ଶ == 0 .alignmentGuide(.trailing) { context in context.width * 2

    } ˞Πϝʔδ
  61. context.width * 2 ϓϨʔϯͳঢ়ଶ == 0 .alignmentGuide(.trailing) { context in

    context.width * 2 } ˞Πϝʔδ
  62. 🙅 .trailingͷσϑΥϧτ஋ ͔Β context.width * 2 ͣΒ͢ .alignmentGuide(.trailing) { context

    in context.width * 2 } 🙆 .trailingͷσϑΥϧτ஋ ͔Β context.width * 2 ʹஔ͖׵͑Δ VStack(alignment: .trailing)
  63. func alignmentGuide( _ g: HorizontalAlignment, computeValue: @escaping (ViewDimensions) -> CGFloat

    ) -> some View alignmentGuide(_:computeValue:) • ୈ2Ҿ਺ͷclosure • ௐ੔ͨ͠஋ʢج४Ґஔ͔ΒͲΕ͘Β͍ͣΒ͔͢ʣΛฦ͢ • Ҿ਺ͷViewDimensions͔Βར༻Ͱ͖Δ΋ͷ • Viewͷwidth, height • ֤Alignment GuideҐஔʢoffset஋ʣ
  64. subscript(guide: VerticalAlignment) -> CGFloat { get } subscript(guide: HorizontalAlignment) ->

    CGFloat { get } ViewDimensions https://developer.apple.com/documentation/swiftui/viewdimensions subscript(explicit guide: VerticalAlignment) -> CGFloat? { get } subscript(explicit guide: HorizontalAlignment) -> CGFloat? { get }
  65. subscript(guide: VerticalAlignment) -> CGFloat { get } subscript(guide: HorizontalAlignment) ->

    CGFloat { get } ViewDimensions https://developer.apple.com/documentation/swiftui/viewdimensions subscript(explicit guide: VerticalAlignment) -> CGFloat? { get } subscript(explicit guide: HorizontalAlignment) -> CGFloat? { get }
  66. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  67. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  68. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  69. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) } == 0 == context.width
  70. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.trailing)

    { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  71. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) } ˞ VStackͰ.leading͕ࢦఆ͞Ε͍ͯͳ͍ͷͰɺ ͜Ε୯ମͰ͸ϨΠΞ΢τʹӨڹ͸ͳ͍
  72. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  73. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) } != 0
  74. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) } == 100
  75. subscript(guide: VerticalAlignment) -> CGFloat { get } subscript(guide: HorizontalAlignment) ->

    CGFloat { get } ViewDimensions https://developer.apple.com/documentation/swiftui/viewdimensions subscript(explicit guide: VerticalAlignment) -> CGFloat? { get } subscript(explicit guide: HorizontalAlignment) -> CGFloat? { get }
  76. subscript(guide: VerticalAlignment) -> CGFloat { get } subscript(guide: HorizontalAlignment) ->

    CGFloat { get } ViewDimensions https://developer.apple.com/documentation/swiftui/viewdimensions subscript(explicit guide: VerticalAlignment) -> CGFloat? { get } subscript(explicit guide: HorizontalAlignment) -> CGFloat? { get }
  77. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[.leading] } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  78. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[explicit: .leading] ?? -50 } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  79. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[explicit: .leading] ?? -50 } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) } มԽͳ͠
  80. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ .alignmentGuide(.leading)

    { _ in 100 } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[explicit: .leading] ?? -50 } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) } มԽͳ͠ != nil == 100
  81. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ //

    .alignmentGuide(.leading) { _ in // 100 // } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[explicit: .leading] ?? -50 } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  82. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ //

    .alignmentGuide(.leading) { _ in // 100 // } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[explicit: .leading] ?? -50 } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  83. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ //

    .alignmentGuide(.leading) { _ in // 100 // } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[explicit: .leading] ?? -50 } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) }
  84. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) // লུ //

    .alignmentGuide(.leading) { _ in // 100 // } .alignmentGuide(.trailing) { context in if context.width < 120 { return context[explicit: .leading] ?? -50 } else if context.width < 180 { return context[.trailing] } else { return -50 } } Color.white.frame(width: 1) } == nil
  85. subscript(guide: VerticalAlignment) -> CGFloat { get } subscript(guide: HorizontalAlignment) ->

    CGFloat { get } ViewDimensions https://developer.apple.com/documentation/swiftui/viewdimensions subscript(explicit guide: VerticalAlignment) -> CGFloat? { get } subscript(explicit guide: HorizontalAlignment) -> CGFloat? { get } σϑΥϧτ஋ɾஔ͖׵͑ΒΕͨ஋Λऔಘ ஔ͖׵͑ΒΕͨ஋Λऔಘʢஔ͖׵͑ΒΕ͍ͯͳ͍৔߹͸ nilʣ
  86. 💡tips

  87. cf. https://developer.apple.com/documentation/swiftui/view/alignmentguide(_:computevalue:)-9mdoh Changing the alignment of one view may have

    effects on surrounding views.
  88. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in // লུ } Color.white.frame(width: 1) } .frame(maxHeight: 500) .border(.white)
  89. VStack(alignment: .trailing, spacing: 20) { Color.red.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in // লུ } Color.red.frame(width: 1) } .frame(maxHeight: 500) .border(.white)
  90. VStack(alignment: .trailing, spacing: 20) { Color.red.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in // লུ } Color.red.frame(width: 1) } .frame(maxHeight: 500) .border(.white)
  91. ֎ଆͷStackͷframe͕มԽ͠͏Δ

  92. ☕ offset(x:y:)

  93. func offset( x: CGFloat = 0, y: CGFloat = 0

    ) -> some View offset(x:y:) https://developer.apple.com/documentation/swiftui/view/offset(x:y:) • ViewΛਫฏ/ਨ௚ํ޲ʹҠಈ͢ΔViewModi fi er
  94. VStack { Text("🐶") Text("🐱") Text("🐰") }

  95. VStack { Text("🐶") Text("🐱") .offset(x: 50, y: 100) Text("🐰") }

  96. cf. https://developer.apple.com/documentation/swiftui/view/offset(x:y:) Use offset(x:y:) to shift the displayed contents by

    the amount speci fi ed in the x and y parameters. The original dimensions of the view aren’t changed by offsetting the contents.
  97. VStack(spacing: 20) { Text("🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰") Text("Offset by passing horizontal & vertical

    distance") .border(Color.green) .padding() } .border(.red) offset(x:y:)
  98. VStack(spacing: 20) { Text("🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰") Text("Offset by passing horizontal & vertical

    distance") .border(Color.green) .offset(x: 20, y: 50) .border(Color.gray) .padding() } .border(.red) offset(x:y:)
  99. VStack(spacing: 20) { Text("🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰") Text("Offset by passing horizontal & vertical

    distance") .border(Color.green) .offset(x: 20, y: 50) .border(Color.gray) .padding() } .border(.red) offset(x:y:)
  100. VStack(spacing: 20) { Text("🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰") Text("Offset by passing horizontal & vertical

    distance") .border(Color.green) .offset(x: 20, y: 50) .border(Color.gray) .padding() } .border(.red) offset(x:y:)
  101. VStack(spacing: 20) { Text("🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰🐰") Text("Offset by passing horizontal & vertical

    distance") .border(Color.green) .offset(x: 20, y: 50) .border(Color.gray) .padding() } .border(.red) offset(x:y:)
  102. alignmentGuide(_:computeValue:) vs. offset(x:y:)

  103. alignmentGuide(_:computeValue:)

  104. alignmentGuide(_:computeValue:) offset(x:y:)

  105. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.gray)
  106. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.gray)
  107. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.gray)
  108. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.orange) .offset(x: 20, y: 50) .border(Color.pink) .offset(x: 20, y: 50) .border(Color.gray)
  109. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.orange) .offset(x: 20, y: 50) .border(Color.pink) .offset(x: 20, y: 50) .border(Color.gray)
  110. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.orange) .offset(x: 20, y: 50) .border(Color.pink) .offset(x: 20, y: 50) .border(Color.gray)
  111. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.orange) .offset(x: 20, y: 50) .border(Color.pink) .offset(x: -20, y: 50) .border(Color.gray)
  112. Text("Offset by passing horizontal & vertical distance") .border(Color.green) .offset(x: 20,

    y: 50) .border(Color.orange) .offset(x: 20, y: 50) .border(Color.pink) .offset(x: -20, y: 50) .border(Color.gray)
  113. ୈষ Custom Alignment Guide

  114. ྫ୊

  115. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle() .fill(.blue) .frame(width:

    100, height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text(“🐰🐢") .font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”) .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text(“Side\nText") .font(.title) Color.white.frame(height: 1) }
  116. None
  117. ղ౴ྫ

  118. extension VerticalAlignment { private struct BlueBarTitleAlignment: AlignmentID { static func

    defaultValue(in context: ViewDimensions) -> CGFloat { context[.bottom] } } static let blueBarTitleAlignment = VerticalAlignment( BlueBarTitleAlignment.self ) }
  119. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text(“Side\nText").font(.title) Color.white.frame(height: 1) }
  120. HStack(alignment: .blueBarTitleAlignment) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text("🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text("Side\nText").font(.title) Color.white.frame(height: 1) }
  121. HStack(alignment: .blueBarTitleAlignment) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar") .font(.title) .alignmentGuide(.blueBarTitleAlignment) { context in context[.firstTextBaseline] } } VStack { Text("🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar").font(.title) .alignmentGuide(.blueBarTitleAlignment) { context in context[.firstTextBaseline] } Text("iOSDC 2022 sample code #1") .font(.caption) } Text("Side\nText").font(.title) Color.white.frame(height: 1) }
  122. ղઆ

  123. Take 1

  124. Built-in Alignment Guides

  125. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle() .fill(.blue) .frame(width:

    100, height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text(“🐰🐢") .font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”) .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text(“Side\nText") .font(.title) Color.white.frame(height: 1) }
  126. HStack(alignment: .firstTextBaseline) { Color.white.frame(height: 1) VStack { Rectangle() .fill(.blue) .frame(width:

    100, height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text(“🐰🐢") .font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”) .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text(“Side\nText") .font(.title) Color.white.frame(height: 1) }
  127. HStack(alignment: .firstTextBaseline) { Color.white.frame(height: 1) VStack { Rectangle() .fill(.blue) .frame(width:

    100, height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text(“🐰🐢") .font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”) .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text(“Side\nText") .font(.title) Color.white.frame(height: 1) }
  128. HStack(alignment: .firstTextBaseline) { Color.white.frame(height: 1) VStack { Rectangle() .fill(.blue) .frame(width:

    100, height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text(“🐰🐢") .font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”) .font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text(“Side\nText") .font(.title) Color.white.frame(height: 1) } ࣮ݱ͍ͨ͠ϨΠΞ΢τ
  129. Take 2

  130. alignmentGuide(_:computeValue:)

  131. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar”).font(.title) } VStack { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1").font(.caption) } Text(“Side\nText").font(.title) Color.white.frame(height: 1) }
  132. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar").font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } } VStack { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } Text("iOSDC 2022 sample code #1").font(.caption) } Text(“Side\nText").font(.title) Color.white.frame(height: 1) }
  133. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar").font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } } VStack { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } Text("iOSDC 2022 sample code #1").font(.caption) } Text(“Side\nText").font(.title) Color.white.frame(height: 1) } มԽͳ͠
  134. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack(alignment: .center) { Rectangle().fill(.blue) .frame(width:

    100, height: 400) Text("Long Long Long Blue Bar").font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } } VStack(alignment: .center) { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } Text("iOSDC 2022 sample code #1").font(.caption) } Text(“Side\nText").font(.title) Color.white.frame(height: 1) } มԽͳ͠
  135. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack(alignment: .center) { Rectangle().fill(.blue) .frame(width:

    100, height: 400) Text("Long Long Long Blue Bar").font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } } VStack(alignment: .center) { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } Text("iOSDC 2022 sample code #1").font(.caption) } Text(“Side\nText").font(.title) Color.white.frame(height: 1) } มԽͳ͠
  136. Built-in Alignment Guides + alignmentGuide(_:computeValue:) StackΛ·͍ͨͰViewΛἧ͑Δ͜ͱ͸Ͱ͖ͳ͍

  137. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar”).font(.title) } VStack { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1").font(.caption) } Text(“Side\nText").font(.title) Color.white.frame(height: 1) }
  138. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar").font(.title) } .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } VStack { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1").font(.caption) } .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } Text(“Side\nText").font(.title) Color.white.frame(height: 1) }
  139. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar").font(.title) } .alignmentGuide(.bottom) { context in context[.firstTextBaseline] } VStack { Text(“🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1").font(.caption) } .alignmentGuide(.bottom) { context in ???????????????? } Text(“Side\nText").font(.title) Color.white.frame(height: 1) } ̎ͭ໨ͷςΩετʹἧ͑Δͪΐ͏Ͳྑ͍஋ΛฦͤΔ…ʁ
  140. Take 3

  141. Custom Alignment Guide

  142. protocol AlignmentID

  143. public protocol AlignmentID { static func defaultValue(in context: ViewDimensions) ->

    CGFloat }
  144. public protocol AlignmentID { static func defaultValue(in context: ViewDimensions) ->

    CGFloat } HStackͳͲͰࢦఆͨ͠ࡍͷσϑΥϧτ஋
  145. private struct BlueBarTitleAlignment: AlignmentID { static func defaultValue(in context: ViewDimensions)

    -> CGFloat { context[.bottom] } }
  146. extension VerticalAlignment { private struct BlueBarTitleAlignment: AlignmentID { static func

    defaultValue(in context: ViewDimensions) -> CGFloat { context[.bottom] } } static let blueBarTitleAlignment = VerticalAlignment( BlueBarTitleAlignment.self ) }
  147. HStack(alignment: .bottom) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text("🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1”) .font(.caption) } Text("Side\nText").font(.title) Color.white.frame(height: 1) }
  148. HStack(alignment: .blueBarTitleAlignment) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar") .font(.title) } VStack { Text("🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar”).font(.title) Text("iOSDC 2022 sample code #1") .font(.caption) } Text("Side\nText").font(.title) Color.white.frame(height: 1) }
  149. HStack(alignment: .blueBarTitleAlignment) { Color.white.frame(height: 1) VStack { Rectangle().fill(.blue) .frame(width: 100,

    height: 400) Text("Long Long Long Blue Bar") .font(.title) .alignmentGuide(.blueBarTitleAlignment) { context in context[.firstTextBaseline] } } VStack { Text("🐰🐢").font(.title) Rectangle().fill(.blue) .frame(width: 150, height: 200) Text("Short Blue Bar").font(.title) .alignmentGuide(.blueBarTitleAlignment) { context in context[.firstTextBaseline] } Text("iOSDC 2022 sample code #1") .font(.caption) } Text("Side\nText").font(.title) Color.white.frame(height: 1) }
  150. • StackΛލ͍ͰViewΛἧ͍͑ͨ Custom Alignment Guide ͷ࢖͍ॴ

  151. • StackΛލ͍ͰViewΛἧ͍͑ͨ • alignmentGuide(_:computeValue:) Λ࢖͍ճ͍ͨ͠ • ViewDimentionsͷ஋͚ͩͰܭࢉͰ͖Δ৔߹ Custom Alignment Guide

    ͷ࢖͍ॴ
  152. VStack(alignment: .trailing, spacing: 20) { Color.white.frame(width: 1) ForEach(["Dog", "Crocodile", "Horse",

    "Rhinoceros"], id: \.self) { Text($0) .font(.largeTitle) .padding() .background(Color.green) } .alignmentGuide(.trailing) { context in context.width * 2 } Color.white.frame(width: 1) }
  153. Stack × Custom Alignment Guide ͷ ੍໿

  154. None
  155. ̎ϲॴἧ͑

  156. ۠੾Γઢ

  157. None
  158. VStack(alignment: .profileListRowTextAlignment, spacing: 8) { // লུ HStack(spacing: 24) {

    Text("ϫΠϯΤΩεύʔτೝఆ൪߸") .font(.caption) Text("1234567890") .font(.caption) } // লུ }
  159. VStack(alignment: .profileListRowTextAlignment, spacing: 8) { // লུ HStack(spacing: 24) {

    Text("ϫΠϯΤΩεύʔτೝఆ൪߸") .font(.caption) Text("1234567890") .font(.caption) .alignmentGuide(.profileListRowTextAlignment) { $0[.leading] - 30 } } // লུʢଞͷTextʹ΋alignmentGuideΛ෇༩ʣ }
  160. VStack(alignment: .profileListRowTextAlignment, spacing: 8) { // লུ HStack(spacing: 24) {

    Text("ϫΠϯΤΩεύʔτೝఆ൪߸") .font(.caption) Text("1234567890") .font(.caption) .alignmentGuide(.profileListRowTextAlignment) { $0[.leading] - 30 } } // লུʢଞͷTextʹ΋alignmentGuideΛ෇༩ʣ }
  161. VStack(alignment: .profileListRowTextAlignment, spacing: 8) { // লུ HStack(spacing: 24) {

    Text("ϫΠϯΤΩεύʔτೝఆ൪߸") .font(.caption) .alignmentGuide(.profileListRowTextAlignment) { $0[.leading] } Text("1234567890") .font(.caption) .alignmentGuide(.profileListRowTextAlignment) { $0[.leading] - 30 } } // লུʢଞͷTextʹ΋alignmentGuideΛ෇༩ʣ }
  162. VStack(alignment: .profileListRowTextAlignment, spacing: 8) { // লུ HStack(spacing: 24) {

    Text("ϫΠϯΤΩεύʔτೝఆ൪߸") .font(.caption) .alignmentGuide(.profileListRowTextAlignment) { $0[.leading] } Text("1234567890") .font(.caption) .alignmentGuide(.profileListRowTextAlignment) { $0[.leading] - 30 } } // লུʢଞͷTextʹ΋alignmentGuideΛ෇༩ʣ } ͦΕͧΕ͕HStack͝ͱҠಈͤ͞ΔͷͰἧΘͳ͍…
  163. • ಉ͡Stack಺ͷෳ਺ͷViewΛἧ͑ΒΕͳ͍ • ج४ͱͳΔ1ͭͷAlignmentʹରͯ͠ର৅ͷViewΛؚΉStack શମͷҐஔΛௐ੔͢Δ࢓૊ΈͷͨΊ Stack × Custom Alignment Guide

    ͷ੍໿
  164. ☕ Grid

  165. VStack { SpeakerHeader() Grid(alignment: .leading, verticalSpacing: 8) { Divider() GridRow

    { Text("ϫΠϯΤΩεύʔτೝఆ൪߸") .lineLimit(1) .font(.caption) Text("1234567890") .font(.caption) } Divider() GridRow { Text("໊લ") .font(.caption) Text("monoqlo") .font(.caption) } GridRow { Text("ి࿩൪߸") .font(.caption) Text("XXX-XXXX-XXXXX") .font(.caption) } } } .padding() .overlay( RoundedRectangle(cornerRadius: 8) .stroke(.gray) ) https://developer.apple.com/documentation/swiftui/grid
  166. ☕ • frame(width:height:alignment:) • frame(minWidth:idealWidth:maxWidth:minHeight:ide alHeight:maxHeight:alignment:)

  167. HStack { Image("monoqloIcon") .resizable() .frame(width: 50, height: 50) .clipShape(Circle()) HStack

    { VStack(alignment: .leading) { Text("monoqlo") .font(.headline) Text("iOSDC 2022") .font(.body) } } .border(.gray) Image(systemName: "heart") .foregroundColor(.pink) .padding() .border(.gray) } .frame(width: 300) .padding() .border(.green)
  168. HStack { Image("monoqloIcon") .resizable() .frame(width: 50, height: 50) .clipShape(Circle()) HStack

    { VStack(alignment: .leading) { Text("monoqlo") .font(.headline) Text("iOSDC 2022") .font(.body) } .frame(maxWidth: .infinity, alignment: .leading) } .border(.gray) Image(systemName: "heart") .foregroundColor(.pink) .padding() .border(.gray) } .frame(width: 300) .padding() .border(.green)
  169. Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022 ⭐ """) .border(.red)

  170. Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022 ⭐ """) .border(.red)

    .frame(alignment: .bottom)) .border(.white)
  171. Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022 ⭐ """) .border(.red)

    .alignmentGuide(.bottom) { $0[.firstTextBaseline] } .frame(alignment: .bottom)) .border(.white)
  172. VStack { Text("top") Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022

    ⭐ """) .border(.red) Text("bottom") }
  173. VStack { Text("top") Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022

    ⭐ """) .border(.red) Text("bottom") } .frame(height: 200, alignment: .init(horizontal: .center, vertical: .frameTextAlignment)) .border(.white)
  174. VStack { Text("top") Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022

    ⭐ """) .border(.red) Text("bottom") } .frame(height: 200, alignment: .init(horizontal: .center, vertical: .frameTextAlignment)) .border(.white) private extension VerticalAlignment { struct FrameTextAlignment: AlignmentID { static func defaultValue(in context: ViewDimensions) -> CGFloat { context[.bottom] } } static let frameTextAlignment = VerticalAlignment( FrameTextAlignment.self ) }
  175. VStack { Text("top") Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022

    ⭐ """) .border(.red) Text("bottom") } .frame(height: 200, alignment: .init(horizontal: .center, vertical: .frameTextAlignment)) .border(.white)
  176. VStack { Text("top") Text(""" ⭐ monoqlo ⭐ ⭐ iOSDC 2022

    ⭐ """) .border(.red) .alignmentGuide(.frameTextAlignment) { $0[.firstTextBaseline] } Text("bottom") } .frame(height: 200, alignment: .init(horizontal: .center, vertical: .frameTextAlignment)) .border(.white)
  177. 🤔 alignmentGuide(_:computeValue:) vs. offset(x:y:)

  178. alignmentGuide(_:computeValue:) offset(x:y:)

  179. alignmentGuide(_:computeValue:) offset(x:y:) ※ Stackͷalignmentʹରͯ͠࢖ͬͨ࣌

  180. • frame(alignment:) • frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight: maxHeight:alignment:) + alignmentGuide(_:computeValue:)

  181. Alignment Guide ೖ໳Ͱ͖ͨͰ͠ΐ͏͔ʁ

  182. ࣗݾ঺հ

  183. @monoqloʢ΋ͷ͘Ζʣ • 2೥લ͔ΒϦΫϧʔτͷਓ • ελσΟαϓϦENGLISH୲౰

  184. None
  185. None
  186. None
  187. Appendix

  188. • Alignment • https://developer.apple.com/documentation/swiftui/alignment • https://developer.apple.com/documentation/swiftui/verticalalignment • https://developer.apple.com/documentation/swiftui/horizontalalignment • https://developer.apple.com/documentation/swiftui/aligning-views-within-a-stack

    • alignmentguide(_:computevalue:) • https://developer.apple.com/documentation/swiftui/view/alignmentguide(_:computevalue:)-9mdoh • https://developer.apple.com/documentation/swiftui/view/alignmentguide(_:computevalue:)-6y3u2 • https://developer.apple.com/documentation/swiftui/viewdimensions Appendix
  189. • Custom Alignment Guide • https://developer.apple.com/documentation/swiftui/aligning-views-across-stacks • https://developer.apple.com/documentation/swiftui/alignmentid • https://developer.apple.com/documentation/swiftui/verticalalignment/init(_:)

    • https://developer.apple.com/documentation/swiftui/horizontalalignment/init(_:) • offset(x:y:) • https://developer.apple.com/documentation/swiftui/view/offset(x:y:) Appendix
  190. • Grid • https://developer.apple.com/documentation/swiftui/grid • Debug • https://developer.apple.com/documentation/swiftui/inspecting-view-layout Appendix