2017-10-17 85 views
0

我有一個UITableView其細胞包含在其上我需要執行三件事一個子視圖:在運行時根據內部的值上不同大小的一個UIView將一個掩模層內的UITableViewCell

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

但是我所看到的,當我運行這段代碼是這樣的效果: enter image description here

在上面的代碼中的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,無濟於事。

我還發現this response to a similar problem,建議將掩碼圖層代碼放在drawRect:內。這實際上爲我解決了99%的問題(拋開了性能問題),但仍然存在一些角落案例(沒有雙關語意思)留在非常長的表格視圖中,我仍然看到錯誤的行爲。

我最後的手段是通過performSelector以0.00001的延遲調用我的舍入函數,它的作用在於,在屏幕消失之前,屏幕上出現大約一秒的錯誤 - 這與理想行爲還很遙遠,更不用說了可怕的代碼,我不得不爲它寫。

有沒有什麼方法可以在UITableViewCell的視圖中使用其正確的運行時框架可靠地應用形狀圖層?

+0

是您有您的細胞的一個子視圖麻煩的看法?如果是這樣,如果你*不*設置圖層蒙版,大小/位置是否正確? – DonMag

+0

@DonMag是的,它是一個子視圖,不,如果我不設置圖層蒙版,所有單元格的輸出框架都是不正確的(但屏幕上的所有內容都是正確的) – Richard

+0

行 - 請參閱我的答案,並參閱如果這會對你有用。 – DonMag

回答

1

我建議創建一個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 

    } 

} 

現在,在單元格中BulletBar設置類的 「欄」 子視圖。使用約束將其固定到右側和底部,並約束高度和寬度。爲寬度約束創建一個IBOutlet,然後根據需要設置barWidthConstraint.constant

該課程本身將處理圓角。

結果:

enter image description here

+0

像一個魅力一樣工作,謝謝! – Richard

2

我認爲你應該做的是,

  1. 坐落在cellForRowAtIndexPath與您當前對象的屬性,嘗試在特定值的設置器的限制。
  2. 呼叫setNeedsLayout這將使未來的呼叫layoutIfNeeded - >layoutSubviews
  3. 在你layoutSubviews,設置圓角。

我希望這會幫助你。

+0

這不能解決問題,不幸的是 – Richard

+0

'setNeedsLayout'''設置了'''layoutSubviews'''的未來調用,嘗試從您設置屬性的位置明確調用'''layoutSubviews'''。 –

+0

我已經嘗試過顯式調用'layoutSubviews'(沒有成功),我想這是因爲在配置單元格的時候,約束沒有被渲染,所以調用'layoutSubviews'將會是毫無意義的 – Richard

相關問題