這一篇我們將實現(xiàn)一個富文本編輯器喜颁,擁有功能:
- 1、斜體曹阔、下劃線混排半开。
- 2、圖文混排
- 3赃份、字體大小寂拆。
- 4、選擇自定義字體抓韩。
- 5纠永、制作長圖片分享到微信朋友圈與微信好友。
- 6谒拴、調(diào)用系統(tǒng)郵件發(fā)送文本尝江。
先來看一下大體的效果吧,還有一些效果將在后面演示:
(寫在最前面彪薛,這個Demo存在大量BUG茂装,我只是通過他來演示一些功能,也許在后面我會做一個完整的APP善延,到時候也會再來寫一遍少态,來說說一些BUG如何處理)。
富文本編輯器在以前需要使用CoreText來實現(xiàn)易遣,但是不得不說這真的是一個不小的工程彼妻,但是在iOS7發(fā)布以后,apple發(fā)布了TextKit豆茫,通過TextKit我們能夠輕松實現(xiàn)很多從前難以實現(xiàn)的功能侨歉。
1、斜體揩魂、下劃線混排幽邓、字體的增大以及減小
在SB中拖入一個UITextView,此后的所有操作都是對這個TextView中的文字進(jìn)行操作火脉,先來看幾行代碼:
<pre><code>
var string = NSMutableAttributedString(attributedString: self.textview.attributedText)
string.addAttribute(NSObliquenessAttributeName, value: 0.5, range: NSMakeRange(0,5))
</code></pre>
我們來解釋一下這一段代碼:
首先牵舵,我們從TextView中獲取了string柒啤,這個string是NSMutableAttributedString類型的,這個類型繼承自String畸颅,但是呢担巩,從名字上我們就可以看出來這個類型,我們可以給字符串添加不同的屬性没炒,我們回到代碼涛癌。這段代碼的第二句我們通過:
func addAttribute(name: String, value: AnyObject, range: NSRange)
這個函數(shù)給字符串添加了屬性,這個API的第1送火、2個參數(shù)就是確定添加的屬性類型拳话,在這里我們添加的就是斜體這個屬性,斜體這個屬性的Value參數(shù)填寫0~1之間的數(shù)值漾脂,在這個我們填寫的是0.5.來看第二個參數(shù)假颇,第二個參數(shù)是添加屬性的范圍,填寫的是一個NSRange類型的值骨稿,應(yīng)該不難理解笨鸡。
以上代碼段的功能就是給textview的字符串的第0個字符開始,連續(xù)五個字符添加斜體的效果坦冠。
是不是十分方便形耗?~~~~~是的。
以上內(nèi)容只是為了演示UITextView中的attributedText屬性辙浑,事實上我們不需要這么做(感謝劉大大激涤,告訴我接下來這種做法)。
在TextView中有一個屬性叫做typingAttributes判呕,xcode對這個屬性的解釋是這樣的automatically resets when the selection changes倦踢,意思就是我們對這個屬性進(jìn)行設(shè)置可以改變接下來改變的文字。
也許這樣說侠草,不能讓人太好的理解辱挥,我們在按鈕中添加以下代碼
<pre><code>
@IBAction func Obliqueness(sender: AnyObject) {
textview.typingAttributes[NSObliquenessAttributeName] = (textview.typingAttributes[NSObliquenessAttributeName] as? NSNumber) == 0 ? 0.5 : 0
}
</code></pre>
當(dāng)** NSObliquenessAttributeName**的值為0時,點擊按鈕將將之改變?yōu)?边涕,為1時則相反晤碘。我們點一下試試,神奇的事情發(fā)生啦啦啦啦~~~接下來我們輸入的文字都變成了斜體功蜓。再次點擊則變回正常园爷。
以此類推,我們寫出下劃線式撼、字體的增大以及減小的代碼童社。
<pre><code>
/**
字體減小
:param: sender
*/
@IBAction func fontincrease(sender: AnyObject) {
self.fontSize -= 2
self.textview.typingAttributes[NSFontAttributeName] = UIFont.systemFontOfSize((CGFloat)(self.fontSize))
}
/**
字體增大
:param: sender
*/
@IBAction func fontdecase(sender: AnyObject) {
self.fontSize += 2
self.textview.typingAttributes[NSFontAttributeName] = UIFont.systemFontOfSize((CGFloat)(self.fontSize))
}
/**
設(shè)置斜體
:param: sender
*/
@IBAction func Obliqueness(sender: AnyObject) {
textview.typingAttributes[NSObliquenessAttributeName] = (textview.typingAttributes[NSObliquenessAttributeName] as? NSNumber) == 0 ? 0.5 : 0
}
/**
設(shè)置下劃線
:param: sender
*/
@IBAction func underline(sender: AnyObject) {
self.textview.typingAttributes[NSUnderlineStyleAttributeName] = (NSUnderlineStyle.StyleSingle.hashValue ) == 0 ? 1 : NSUnderlineStyle.StyleSingle.hashValue
}
/**
</code></pre>
實現(xiàn)方法都是類似的,十分方便的已經(jīng)實現(xiàn)了很多功能著隆,這放在以前是不可能的(其實我不知道以前實現(xiàn)究竟有多復(fù)雜——5础)甘改。
2、插入圖片灭抑。
前面我們知道TextView存在一個屬性叫做attributedText,插入圖片需要做的就是在TextView的這個屬性中添加圖片抵代,上代碼腾节。
<pre><code>
//1
var string = NSMutableAttributedString(attributedString: self.textview.attributedText)
//2
var textAttachment = NSTextAttachment()
textAttachment.image = img
//3
var textAttachmentString = NSAttributedString(attachment: textAttachment)
var countString:Int = count(self.textview.text) as Int
string.insertAttributedString(textAttachmentString, atIndex: countString)
//4
textview.attributedText = string
</code></pre>
- 1、獲取當(dāng)前的attributedString
- 2荤牍、新建一個NSTextAttachment案腺,設(shè)置他的圖片屬性
- 3、將剛剛創(chuàng)建的NSTextAttachment康吵,添加在原本的attributedString的最后面
- 4劈榨、重定義** textview.attributedText **
以上代碼中出現(xiàn)一個變量img,這個變量就是從系統(tǒng)相冊獲取圖片晦嵌,代碼如下:
<pre><code>
@IBAction func photeSelect(sender: AnyObject) {
var sheet:UIActionSheet
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
sheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "取消", destructiveButtonTitle: nil, otherButtonTitles: "從相冊選擇", "拍照")
}else{
sheet = UIActionSheet(title:nil, delegate: self, cancelButtonTitle: "取消", destructiveButtonTitle: nil, otherButtonTitles: "從相冊選擇")
}
sheet.showInView(self.view)
}
func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
var sourceType = UIImagePickerControllerSourceType.PhotoLibrary
if(buttonIndex != 0){
if(buttonIndex==1){ //相冊
sourceType = UIImagePickerControllerSourceType.PhotoLibrary
}else{
sourceType = UIImagePickerControllerSourceType.Camera
}
let imagePickerController:UIImagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.allowsEditing = true//true為拍照同辣、選擇完進(jìn)入圖片編輯模式
imagePickerController.sourceType = sourceType
self.presentViewController(imagePickerController, animated: true, completion: {
})
}
}
</code></pre>
首先是彈出一個alertView,讓你進(jìn)行選擇惭载,選擇以后旱函,將調(diào)用下面的方法,進(jìn)入到相冊進(jìn)行選擇圖片描滔。在這里你需要繼承幾個協(xié)議棒妨,不然在選擇以后不會觸發(fā)下面的方法:UIActionSheetDelegate,UIImagePickerControllerDelegate。同時進(jìn)入相冊你需要添加幾個庫:AssetsLibrary.framework和MobileCoreServices.framework含长。具體代碼解釋在這里就不行進(jìn)解釋券腔,今天我們把重點放在富文本的實現(xiàn)上。當(dāng)你選擇圖片以后拘泞,將促發(fā)以下方法纷纫,這也是前面添加的協(xié)議的功能。
<pre><code>
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]){
var string = NSMutableAttributedString(attributedString: self.textview.attributedText)
var img = info[UIImagePickerControllerEditedImage] as! UIImage
img = self.scaleImage(img)
var textAttachment = NSTextAttachment()
textAttachment.image = img
var textAttachmentString = NSAttributedString(attachment: textAttachment)
var countString:Int = count(self.textview.text) as Int
string.insertAttributedString(textAttachmentString, atIndex: countString)
textview.attributedText = string
self.textview.becomeFirstResponder()
picker.dismissViewControllerAnimated(true, completion: nil)
}
</code></pre>
同時在這個函數(shù)中我們給文本插入圖片田弥,插入方法在前面已經(jīng)說過了涛酗。
當(dāng)我們選擇圖片以后你會發(fā)現(xiàn)由于圖片太大,所以在界面上只能顯示一部分偷厦,那么我們就需要壓縮圖片商叹,壓縮方法如下:
<pre><code>
func scaleImage(image:UIImage)->UIImage{
UIGraphicsBeginImageContext(CGSizeMake(self.view.bounds.size.width, image.size.height(self.view.bounds.size.width/image.size.width)))
image.drawInRect(CGRectMake(0, 0, self.view.bounds.size.width, image.size.height(self.view.bounds.size.width/image.size.width)))
var scaledimage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return scaled image
}
</code></pre>
這個方法將圖片的寬度設(shè)置為屏幕的寬度,高度按比例縮放只泼。
好的~~~~~我們終于實現(xiàn)了插入圖片剖笙,其實在這里有一個很大的問題,就是下面這句話:
<pre><code>
textview.attributedText = string
</code></pre>
我們每次插入圖片都將TextView的內(nèi)容全部改變了一次请唱,這樣的做法弥咪,先不提在大量文字的情況下可能造成的卡頓問題过蹂,同時造成了編排問題,有同學(xué)可能已經(jīng)發(fā)現(xiàn)了聚至,當(dāng)我們用這樣的方法插入圖片以后酷勺,當(dāng)我們再次改變屬性的時候,視圖將會瞬間調(diào)到最上面扳躬,原因就是這句話脆诉。至于如何解決~~~~還沒想到——!
3贷币、選擇字體
改變字體的方法其實和我們設(shè)置斜體击胜,下劃線等是一樣的,方法如下:
<pre><code>
func lovefont(sender:AnyObject){
self.textview.typingAttributes[NSFontAttributeName] = UIFont(name: "1-", size: (CGFloat)(self.fontSize))
}
</code></pre>
那么我們現(xiàn)在的問題就是自定義字體了役纹,畢竟xcode的字體大多不支持中文偶摔,同時中文顯示的時候不那么優(yōu)雅,我們要說的就是自定義字體促脉。
加載自定義字體辰斋,并不是太過復(fù)雜,我在簡書看到這篇文章描述加載自定義字體就感覺寫的很好嘲叔,http://www.reibang.com/p/d728570bdf7b 小伙伴們有興趣的話自行跳轉(zhuǎn)過去看吧亡呵,這里就不重復(fù)介紹了。
4硫戈、制作長圖片分享到微信朋友圈與微信好友锰什。
那么我們需要做的第一步就是制作長圖片,代碼如下:
<pre><code>
func madelongPicture() -> UIImage {
var image : UIImage!
UIGraphicsBeginImageContext(self.textview.contentSize)
var savedContentOffset = self.textview.contentOffset
var savedFrame = self.textview.frame
self.textview.contentOffset = CGPointZero
self.textview.frame = CGRectMake(0, 0, self.textview.contentSize.width, self.textview.contentSize.height)
self.textview.layer.renderInContext(UIGraphicsGetCurrentContext())
image = UIGraphicsGetImageFromCurrentImageContext()
self.textview.contentOffset = savedContentOffset
self.textview.frame = savedFrame
UIGraphicsEndPDFContext()
return image
}
</code></pre>
TextView繼承自ScorllView丁逝,所以我們只需要給TextView進(jìn)行截圖汁胆,就可以制作一張長圖片了,方法如上霜幼。然后我們需要做的就是調(diào)用微信給我們的API嫩码,將圖片分享到朋友圈。
其實里頭已經(jīng)講的很清楚了琢感,有不明白的親可以留言哦~
5丢间、調(diào)用系統(tǒng)郵件發(fā)送文本
調(diào)用系統(tǒng)郵件,你可以將剛剛寫好的文章或者啥的發(fā)送給好朋友驹针,或者交給老師檢查~~~~~~~首先我們還是得制作長圖片烘挫,制作方法上面已經(jīng)講過了,就不重復(fù)累贅了柬甥,這里講一下如何調(diào)用系統(tǒng)郵件饮六。
首先你得繼承一個協(xié)議:MFMailComposeViewControllerDelegate
然后代碼如下:
<pre><code>
@IBAction func email(sender: AnyObject) {
UIApplication.sharedApplication().keyWindow?.endEditing(true)
var configuredMailComposeViewController = MailComposeViewController()
if canSendMail() {
presentViewController(configuredMailComposeViewController, animated: true, completion: nil)
} else {
showSendMailErrorAlert()
}
}
func MailComposeViewController() -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(nil)
mailComposerVC.setSubject(nil)
mailComposerVC.setMessageBody(self.textview.text, isHTML: false)
var addPic = self.madelongPicture()
var imageData = UIImagePNGRepresentation(addPic)
mailComposerVC.addAttachmentData(imageData, mimeType: "", fileName: "longPicture.png")
return mailComposerVC
}
func canSendMail() -> Bool {
return MFMailComposeViewController.canSendMail()
}
func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
controller.dismissViewControllerAnimated(true, completion: nil)
}
func showSendMailErrorAlert() {
let sendMailErrorAlert = UIAlertView(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", delegate: self, cancelButtonTitle: "OK")
sendMailErrorAlert.show()
}
</code></pre>
代碼就在上面了其垄,自己感受一下的,解釋不動了卤橄。
效果如下:
接下來也許會造個輪子绿满,同時解決所有的BUG(至少我能發(fā)現(xiàn)的)。
代碼已上傳Github:https://github.com/superxlx/textDemo
親們窟扑,自己下載代碼感受一下棒口,然后喜歡的換請點個喜歡同時關(guān)注一下我。