簡體   English   中英

在UITableViewCell內的不同大小的UIView上放置遮罩層

[英]Put a mask layer on a UIView of varying size inside UITableViewCell

我有一個UITableView其單元格包含一個子視圖,我需要在該子視圖上執行三件事:

  1. 在運行時根據此單元格特定對象內部的值更改其寬度約束
  2. 根據相同的值更改其背景顏色
  3. 圓角化視圖的左上角和左下角,但將角保持在右側(因此, layer.cornerRadius是不可選項)

我在自定義UITableViewCell子類中使用以下代碼來僅在視圖的一側實現圓角效果,這是我從tableView:cellForRowAt:調用的:

func roundLeadingEdgesOfBar() {
    let roundedLayer = CAShapeLayer()
    roundedLayer.bounds = viewInQuestion.frame
    roundedLayer.position = viewInQuestion.center
    roundedLayer.path = UIBezierPath(roundedRect: viewInQuestion.bounds,
                                     byRoundingCorners: [.topLeft, .bottomLeft],
                                     cornerRadii: CGSize(width: 2, height: 2)).cgPath
    viewInQuestion.layer.mask = roundedLayer
    print("frame: \(viewInQuestion.frame)")
}

但是,運行此代碼時看到的是這樣的效果: 在此處輸入圖片說明

上面的代碼中的print語句產生以下輸出,指示每次在屏幕上清晰顯示時, viewInQuestion都具有相同的幀:

frame: (175.0, 139.5, 200.0, 5.0)
frame: (175.0, 139.5, 200.0, 5.0)
frame: (175.0, 139.5, 200.0, 5.0)
frame: (175.0, 139.5, 200.0, 5.0)

因此,我假設在調用此函數時尚未呈現對視圖的寬度約束。 當我向上滾動整個表格視圖直到所有單元格都不在視圖中,然后再將它們滾動回視圖時,一切看起來都正確,並且打印的框架都不同,就像我期望的那樣:

frame: (136.5, 79.5, 238.5, 5.0)
frame: (169.5, 79.5, 205.5, 5.0)
frame: (226.0, 79.5, 149.0, 5.0)
frame: (247.5, 79.5, 127.5, 5.0)

我已經在SO上閱讀了幾次,以執行依賴於layoutSubviews內已施加的約束的代碼,但這給了我相同的結果。 我什至嘗試從tableView:willDisplay:forRowAt:調用roundLeadingEdgesOfBar ,但無濟於事。

我還發現了對類似問題的響應,該問題建議將遮罩層代碼放入drawRect: 這實際上為我解決了99%的問題(不考慮性能問題),但是對於很長的表視圖,仍然還有一些極端的情況(沒有雙關語),但我仍然看到錯誤的行為。

我最后的手段是通過打電話給我取整函數performSelector有0.00001延遲,這在您看到的錯誤有關屏幕一秒鍾之前,然后消失感的作品-從理想的行為還有差距,更別說可怕的代碼,我有為此寫。

是否有任何方法可以使用正確的運行時框架將形狀層可靠地應用到UITableViewCell內的視圖上?

我認為您應該做的是,

  1. cellForRowAtIndexPath設置與當前對象相關的屬性,嘗試在該特定值的設置器中設置約束。
  2. 調用setNeedsLayout ,它將在以后調用layoutIfNeeded > layoutSubviews
  3. 在您的layoutSubviews ,設置圓角。

我希望這能幫到您。

建議不要創建一個“使邊緣變圓”的函數,而建議創建一個UIView子類並讓它處理該圓角。

例如:

class BulletBar: UIView {

    override func layoutSubviews() {

        let roundedLayer = CAShapeLayer()

        roundedLayer.frame = bounds

        roundedLayer.path = UIBezierPath(roundedRect: bounds,
                                         byRoundingCorners: [.topLeft, .bottomLeft],
                                         cornerRadii: CGSize(width: 2, height: 2)).cgPath
        layer.mask = roundedLayer

    }

}

現在,將單元格中“ bar”子視圖的類設置為BulletBar。 使用約束將其固定在右側和底部,並限制高度和寬度。 為寬度約束創建一個IBOutlet ,然后根據需要設置barWidthConstraint.constant

班級本身將處理所有問題。

結果:

在此處輸入圖片說明

暫無
暫無

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

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