簡介
在產品開發過程中,有可能會遇到這樣一個情況:一個UILabel設計為僅能顯示一行,但是在小屏手機中,因為寬度不夠,最終會顯示省略號...。 但是這些資訊又比較重要、不能省略,卻沒有充足的空間換行顯示。 那麼問題來了,該怎麼辦呢?這個時候,聰明的產品經理摸了摸下巴,突然雙眼放光“用跑馬燈啊”
好吧,既然產品都給出了精妙絕倫的方案,程式設計師的使命就是義無反顧地實現它!
Github地址
喜歡就給顆小星星喲❤️ JXMarqueeView地址️
動圖預覽
-
JXMarqueeType.left
:往左滾動 -
JXMarqueeType.right
:往右滾動 -
JXMarqueeType.reverse
:迴圈反轉 -
圖片滾動
-
自定義View
原理
- 使用CADisplayLink,每次螢幕重新整理的時候,調整檢視的位置就行。為了達到迴圈顯示,需要新增兩個一樣的檢視。
- 為了擴大跑馬燈的使用範圍,我進行了抽象化處理,並沒有寫死用UILabel來實現,而是暴露了一個屬性
contentView: UIView
。只要是UIView及其子類,都可以用來進行跑馬燈顯示。對於複雜的檢視,需要自己重寫contentView的sizeThatFits方法,返回正確的size即可。
這裡分享兩個騷操作:
- 如何實現UIView的拷貝?
//騷操作:UIView是沒有遵從拷貝協議的。可以通過UIView支援NSCoding協議,間接來複制一個檢視
let otherContentViewData = NSKeyedArchiver.archivedData(withRootObject: validContentView)
let otherContentView = NSKeyedUnarchiver.unarchiveObject(with: otherContentViewData) as! UIView
otherContentView.frame = CGRect(x: validContentView.bounds.size.width + contentMargin, y: 0, width: validContentView.bounds.size.width, height: self.bounds.size.height)
containerView.addSubview(otherContentView)
複製程式碼
- 如何斷開CADisplayLink的迴圈引用? 大家知道CADisplayLink和NSTimer都會對Target強持有,Target一般也會強持有它們。如果使用閉包回撥的API,可以解決這個問題,但是這些API要求iOS的系統都比較高。所以,還是需要直面這個問題。
override func willMove(toSuperview newSuperview: UIView?) {
//騷操作:當檢視將被移除父檢視的時候,newSuperview就為nil。在這個時候,停止掉CADisplayLink,斷開迴圈引用,檢視就可以被正確釋放掉了。
if newSuperview == nil {
self.stopMarquee()
}
}
複製程式碼
使用
- UILabel使用示例
let label = UILabel()
label.textColor = UIColor.red
label.font = UIFont.systemFont(ofSize: 30, weight: .medium)
label.text = "abcdefghijklmnopqrstuvwxyz"
marqueeView.contentView = label
marqueeView.contentMargin = 50
marqueeView.marqueeType = .left
self.view.addSubview(marqueeView)
複製程式碼
- UIImageView使用示例
let imageView = UIImageView(image: UIImage(named: "haizeiwang.jpeg"))
imageView.contentMode = .scaleAspectFill
marqueeView.contentView = imageView
marqueeView.marqueeType = .reverse
self.view.addSubview(marqueeView)
複製程式碼
- 拷貝自定義View
如果contentView帶有圓角、陰影等,通過NSCoding協議拷貝的View會丟失掉這些資訊。這種特殊情況需要自己重新建立一個同樣的自定義View。
重寫JXMarqueeViewCopyable
協議的func copyMarqueeView() -> UIView
方法即可。具體可以參考demo裡面的原始碼。
Github地址
喜歡就給顆小星星喲❤️ JXMarqueeView地址️