SwiftUI .rotationEffect () đóng khung và bù đắp


8

Khi áp dụng .rotationEffect () cho Văn bản, nó sẽ xoay văn bản như mong đợi, nhưng khung của nó vẫn không thay đổi. Điều này trở thành một vấn đề khi xếp chồng các chế độ xem xoay vòng với các chế độ xem không được xoay, chẳng hạn như với VStack của HStack, khiến chúng bị chồng chéo.

Ban đầu tôi nghĩ rotationEffect chỉ đơn giản là cập nhật khung của Văn bản thành dọc, nhưng đây không phải là trường hợp.

Tôi đã thử cài đặt thủ công kích thước khung hình và (nếu cần, bù đắp) Văn bản, loại công việc nào, nhưng tôi không thích giải pháp này vì nó yêu cầu một số dự đoán và kiểm tra xem Văn bản sẽ xuất hiện ở đâu, lớn đến mức nào khung, v.v.

Đây chỉ là cách văn bản xoay được thực hiện, hoặc có một giải pháp thanh lịch hơn cho điều này?

struct TextAloneView: View {

    var body: some View {
        VStack {
            Text("Horizontal text")
            Text("Vertical text").rotationEffect(.degrees(-90))
        }
    }
}

Văn bản chồng chéo

Câu trả lời:


6

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()
        }
    }
}

0

RotationEffect nhận một đối số thứ hai là điểm neo, nếu bạn bỏ qua nó - mặc định là .center.

Hãy thử điều này thay thế:

.rotationEffect(.degrees(-90), anchor: .bottomTrailing)

4
Có một lý do .rotationEffect () khiến khung hình không thay đổi? Ví dụ: nếu tôi kẹp văn bản xoay giữa hai dòng văn bản nằm ngang: bên trên và bên dưới nó, tại sao VStack đặt các văn bản như thể tất cả chúng đều nằm ngang?
EZhou00
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.