? ? ? ?經(jīng)過多番嘗試困鸥, 使用NSMutableAttributedString搭配CoreText來實現(xiàn)較為簡單和靈活。
? ? ? ?如果想要試用UILabel來做,通過限制label寬度,每一個字符換一行來實現(xiàn)的話,哪怕是暫時實現(xiàn)了效果者填, 也終是害人害己,先看看效果圖:
做法:
```swift
let text = "我總想要穿越人海和潮流\n但穿越不了的是你我的鴻溝\nso this way \n 終究還是要自己走\n……\n嗯呀"
? ? ? ? let style = NSMutableParagraphStyle.init()
? ? ? ? style.lineSpacing = 10
//這個對齊方式做葵,對豎直排版同樣有效占哟,左對齊對應(yīng)豎直排版的頭部對齊,右對齊對應(yīng)尾部對齊
? ? ? ?style.alignment = .right
? ? ? ? style.firstLineHeadIndent = 2
? ? ? ? let number1 = NSNumber.init(value: NSWritingDirection.rightToLeft.rawValue)
? ? ? ? let number2 = NSNumber.init(value: NSWritingDirectionFormatType.embedding.rawValue)
? ? ? ? let attriStr = NSMutableAttributedString.init(string: text, attributes: [.foregroundColor: UIColor.white,.font:UIFont.exoBoldFont(size: 18), .verticalGlyphForm: true,.writingDirection:[number1,number2],.paragraphStyle:style])
? ? ? ? let ttLable = TestTextLabel()
? ? ? ? ttLable.attributeStr = attriStr
? ? ? ? self.view.addSubview(ttLable)
? ? ? ? ttLable.sizeToFit()
? ? ? ? ttLable.snp.makeConstraints { (make) in
? ? ? ? ? ? make.center.equalToSuperview()
? ? ? ? ? ? make.width.equalTo(400)
? ? ? ? ? ? make.height.equalTo(400)
? ? ? ? }
//自定義一個label 繼承UIView
class TestTextLabel: UIView {
? ? var attributeStr:NSMutableAttributedString?
? ? var contentSize:CGSize = .zero
? ? overrideinit(frame:CGRect) {
? ? ? ? super.init(frame: frame)
? ? ? ? self.backgroundColor = .black
? ? }
? ? requiredinit?(coder:NSCoder) {
? ? ? ? fatalError("init(coder:) has not been implemented")
? ? }
? ? overridefuncdraw(_rect:CGRect) {
? ? ? ? super.draw(rect)
? ? ? ? let context = UIGraphicsGetCurrentContext()
? ? ? ? context?.textMatrix= .identity
? ? ? ? //CFAttributedString
? ? ? ? letattrString =self.attributeStr!asCFAttributedString
? ? ? ? let framesetter = CTFramesetterCreateWithAttributedString(attrString)
? ? ? ? //作用范圍
? ? ? ? letrangeAll =CFRangeMake(0,self.attributeStr?.length??0)
? ? ? ? varfitRange:CFRange= .init()
? ? ? ? //獲取適應(yīng)的尺寸。豎直展示這里設(shè)置height為無窮大榨乎,width為0怎燥,意思就是,高度可以無限長蜜暑,寬度由AttributedString的文字決定铐姚, 如果想要設(shè)置為橫著展示,則width設(shè)置為無窮大肛捍, height設(shè)置為0
? ? ? ? lets =CTFramesetterSuggestFrameSizeWithConstraints(framesetter, rangeAll,nil,CGSize.init(width:0, height:CGFloat(MAXFLOAT)), &fitRange)
? ? ? ? //coretext的原點坐標(biāo)(0,0)在左下角隐绵,UIKit的原點坐標(biāo)(0,0)系在左上角,這里要把UIKit的坐標(biāo)轉(zhuǎn)為
? ? ? ? context?.translateBy(x:0, y:self.height)
? ? ? ? //翻轉(zhuǎn)矩陣, 把畫面翻轉(zhuǎn)過來拙毫, 如果不設(shè)置這個依许,那么出現(xiàn)的效果就好像是照鏡子一樣,可以自行嘗試
? ? ? ? context?.scaleBy(x:1, y:-1)
? ? ? ? //設(shè)置坐標(biāo) L 形坐標(biāo)系, 因為原本是橫著展示的恬偷,現(xiàn)在要豎直展示,所以需要交換s的寬高帘睦, s.width實際上現(xiàn)在變成了文字的高度
? ? ? ? letframeRect =CGRect.init(x: (self.width-s.height)/2.0, y: (self.height-s.width)/2.0, width: s.height, height: s.width)
? ? ? ? //筆畫路徑
? ? ? ? letframePath:CGPath=CGPath.init(rect: frameRect, transform:nil)
? ? ? ? //.leftToRight 豎直狀態(tài)袍患,從左邊往右讀,.rightToLeft從右往左讀竣付,.topToBottom 橫著的狀態(tài)
? ? ? ? /*如果是豎直的狀態(tài)诡延, 需要attributeString 也設(shè)置為豎直的形式
?? ? ? ? var attriStr = NSMutableAttributedString.init(string: text, attributes: [.foregroundColor: UIColor.red,.font:UIFont.exoBoldFont(size: 14), .verticalGlyphForm: true])
? ? ? ? ? 也就是這句代碼:.verticalGlyphForm: true
? ? ? ? */
? ? ? ? letprogressionNumber =NSNumber.init(value:CTFrameProgression.rightToLeft.rawValue)
? ? ? ? // CTFrameProgression 一定要先轉(zhuǎn)成number類型,否則會crash
?? ? ? letdic = [kCTFrameProgressionAttributeName:progressionNumberasCFNumber]
? ? ? ? letframe =CTFramesetterCreateFrame(framesetter, rangeAll, framePath, dicasCFDictionary)
? ? ? ? CTFrameDraw(frame, context!)
? ? }
}
```
效果圖: