簡體   English   中英

SwiftUI 查看尺寸(父/子關系)

[英]SwiftUI View Sizing (Parent/Child Relationship)

我正在通過一些示例來熟悉 SwiftUI,但我遇到了尺寸問題。

我已經習慣了 UIKit 處理調整視圖大小的方式,使用 AutoLayout 您基本上可以為其子級設置父級大小。 SwiftUI 似乎不是這種情況。

我讀過的所有內容都顯示了如何在孩子上使用 GeometryReader 來獲取其父母的大小,然后孩子可以選擇自己的大小,但我還沒有看到如何從父母那里獲得孩子的大小.

假設我有以下代碼:

struct ContentView: View {
    var body: some View {
        Text("This is Text").ripple(rippleColor: .lightGray, rippleOpacity: 0.5)
    }
}

ipple ripple()是 function 的擴展,它添加了一個自定義ViewModifier ,該 ViewModifier 將內容覆蓋到UIViewRepresentable視圖上,以便在點擊時創建材質波紋效果。

struct RippleModifier: ViewModifier {
    let rippleColor: UIColor
    let rippleOpacity: Float

    func body(content: Content) -> some View {
        RippleView(
            rippleColor: rippleColor,
            rippleOpacity: rippleOpacity
        )
        .overlay(content)
    }
}

extension View {
    func ripple(rippleColor: UIColor, rippleOpacity: Float) -> some View {
        modifier(
            RippleModifier(
                rippleColor: rippleColor,
                rippleOpacity: rippleOpacity
            )
        )
    }
}

我遇到的問題是,當我只有Text時,它會將其框架設置為適合其內容(字符串)。 當我向它添加.ripple()修飾符時,框架就會變成整個屏幕。

使用 UIKit,我只需添加一些約束來將 UILabel 固定到父級,我會讓它決定父級的大小。

有沒有辦法處理 SwiftUI?

獎金問題:

相關但不相關,我如何讓Text上的點擊進入它覆蓋的視圖? 當點擊視圖框架內的任何位置時,波紋將激活並正確動畫,但直接點擊文本本身除外。

編輯:

這是 UIViewRepresentable 視圖的部分代碼。

struct RippleView: UIViewRepresentable {
    var rippleColor: UIColor = .systemGray
    var rippleOpacity: Float = 0.5

    func makeUIView(context: Context) -> UIRippleView {
        UIRippleView()
    }

    func updateUIView(
        _ uiView: UIRippleView,
        context: UIViewRepresentableContext<RippleView>
    ) {
        uiView.rippleColor = rippleColor
        uiView.rippleOpacity = rippleOpacity
    }
}

open class UIRippleView: UIView {
    open var rippleColor: UIColor = .systemGray {
        didSet {
            rippleLayer.fillColor = rippleColor.cgColor
        }
    }

    open var rippleOpacity: Float = 0.5 {
        didSet {
            rippleLayer.opacity = rippleOpacity
        }
    }

    private lazy var rippleLayer: CAShapeLayer = {
        let layer = CAShapeLayer()
        layer.opacity = 0.0

        self.layer.insertSublayer(layer, at: 0)

        return layer
    }()

    public override init(frame: CGRect) {
        super.init(frame: frame)
        clipsToBounds = true
    }

    public required init?(coder: NSCoder) {
        super.init(coder: coder)
        clipsToBounds = true
    }
}

該視圖有一個擴展,它覆蓋了觸摸函數來計算點擊發生的位置並執行動畫,但這只是修改了rippleLayerpath

您可以像這樣將overlay更改為background

struct RippleModifier: ViewModifier {
    let rippleColor: UIColor
    let rippleOpacity: Float

    func body(content: Content) -> some View {
        content.background(
            RippleView(
                rippleColor: rippleColor,
                rippleOpacity: rippleOpacity
        ))
    }
}

所以RippleViewcontent中獲取大小約束,而不是相反。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM