一位使用者@NaThan INN 反饋了關於Widget小元件的Bug,他提到日期的一行文字無法顯示,後來又收到一位使用者反饋了同樣的問題。
我在手機上試了很多次,在模擬器上也試過了,都無法找出是什麼問題。後來我發現使用者給的截圖中,字型的大小和模擬器上有些差別,通過對系統設定字型大小,我發現了問題的根源。
因為開發之初將cell的高定位了固定的55,但是這個值隨著系統字型大小的設定,影響了解析度的處理,Cell在不同的系統字型下有不同的高度。
解決方案:將固定高度改為自適應高度。
方案策略:摺疊狀態下的高度作為自適應的參考高度。
第一步:檢測Widget的摺疊和展開
在Class
中新增 NCWidgetProviding
,同時新增一個儲存高度的變數cellHeight
。這樣才能檢測Widget的狀態,同時獲取高度儲存後使用。
第二步:獲取Widget總體高度
具體程式碼如下,其中NCWidgetDisplayMode.compact
表示摺疊狀態,NCWidgetDisplayMode.expanded
表示展開狀態。
在OneDay中,摺疊狀態只顯示兩行,所以每個Cell的高度為總體高的的1/2,也就是maxSize.height/2
,同時這個高度會作為展開狀態下其他Cell的高度。
當然,這個函式中我還順便把展開狀態的高度做了,根據資料的個數去計算高度。
//摺疊change size
func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
if activeDisplayMode == NCWidgetDisplayMode.compact {
self.preferredContentSize = CGSize(width:maxSize.width,height: maxSize.height)
self.activeDisplayIndex = 0
self.cellHeight = Int(maxSize.height/2)
print("cellHeight",self.cellHeight)
}else{
let hei = CGFloat((self.cellHeight * self.number)+self.cellHeight+5)
self.preferredContentSize = CGSize(width: maxSize.width,height:hei )
self.activeDisplayIndex = 1
print("cellHeight",self.cellHeight)
}
// self.eventsTable.reloadData()
}
複製程式碼
第三步:給Tableview載入高度
獲取高度之後來使用就很簡單了,直接用heightForRowAt。
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return CGFloat(self.cellHeight)
}
複製程式碼
第四步:注意事項和重新載入
注意要給 cellHeight一個初始值,一般推薦50~55;
var cellHeight:Int = 50
複製程式碼
因為widget通常是載入好的,所以在viewWillAppear
中加入tableview
的reloadData
方法,以便在使用者改變系統字型後隨時改變。
self.eventsTable.reloadData()
複製程式碼
最後:看看效果
其實,Widget小元件自適應的效果,看了幾個應用都沒有處理得很好,往往容易被忽視。我手機裡的應用,workflow應該也是這樣類似的解決方案,以便應對系統字型設定帶來widget適配問題。
最後,感謝NaThan INN使用者的反饋,不然真的很難發現,這項特性將在OneDay 2.4.0版本中正式釋出。
GitHub:OneSwift - iOS Tips Based On Swift
微博:xDEHANG