Bạn cần phải tự điều chỉnh khung trong trường hợp này. Điều đó đòi hỏi phải chụp khung hình là gì, và sau đó áp dụng điều chỉnh.
Đầu tiên, để chụp khung hình hiện có, hãy tạo một tùy chọn , đó là một hệ thống để truyền dữ liệu từ chế độ xem con cho cha mẹ của chúng:
private struct SizeKey: PreferenceKey {
static let defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
extension View {
func captureSize(in binding: Binding<CGSize>) -> some View {
overlay(GeometryReader { proxy in
Color.clear.preference(key: SizeKey.self, value: proxy.size)
})
.onPreferenceChange(SizeKey.self) { size in binding.wrappedValue = size }
}
}
Điều này tạo ra một .captureSize(in: $binding)
phương thức mới trên Lượt xem.
Sử dụng điều đó, chúng ta có thể tạo một loại Chế độ xem mới xoay khung của nó:
struct Rotated<Rotated: View>: View {
var view: Rotated
var angle: Angle
init(_ view: Rotated, angle: Angle = .degrees(-90)) {
self.view = view
self.angle = angle
}
@State private var size: CGSize = .zero
var body: some View {
// Rotate the frame, and compute the smallest integral frame that contains it
let newFrame = CGRect(origin: .zero, size: size)
.offsetBy(dx: -size.width/2, dy: -size.height/2)
.applying(.init(rotationAngle: CGFloat(angle.radians)))
.integral
return view
.fixedSize() // Don't change the view's ideal frame
.captureSize(in: $size) // Capture the size of the view's ideal frame
.rotationEffect(angle) // Rotate the view
.frame(width: newFrame.width, // And apply the new frame
height: newFrame.height)
}
}
Và để thuận tiện, một phần mở rộng để áp dụng nó:
extension View {
func rotated(_ angle: Angle = .degrees(-90)) -> some View {
Rotated(self, angle: angle)
}
}
Và bây giờ mã của bạn sẽ hoạt động như bạn mong đợi:
struct TextAloneView: View {
var body: some View {
VStack {
Text("Horizontal text")
Text("Vertical text").rotated()
}
}
}