干货|swift,富文本编辑器

这一篇我们将实现一个富文本编辑器,拥有功能:

  • 1、斜体、下划线混排。
  • 2、图文混排
  • 3、字体大小。
  • 4、选择自定义字体。
  • 5、制作长图片分享到微信朋友圈与微信好友。
  • 6、调用系统邮件发送文本。

先来看一下大体的效果吧,还有一些效果将在后面演示:
(写在最前面,这个Demo存在大量BUG,我只是通过他来演示一些功能,也许在后面我会做一个完整的APP,到时候也会再来写一遍,来说说一些BUG如何处理)。

干货|swift,富文本编辑器_第1张图片
1.png

富文本编辑器在以前需要使用CoreText来实现,但是不得不说这真的是一个不小的工程,但是在iOS7发布以后,apple发布了TextKit,通过TextKit我们能够轻松实现很多从前难以实现的功能。


1、斜体、下划线混排、字体的增大以及减小
在SB中拖入一个UITextView,此后的所有操作都是对这个TextView中的文字进行操作,先来看几行代码:


var string = NSMutableAttributedString(attributedString: self.textview.attributedText)
string.addAttribute(NSObliquenessAttributeName, value: 0.5, range: NSMakeRange(0,5))

我们来解释一下这一段代码:
首先,我们从TextView中获取了string,这个string是NSMutableAttributedString类型的,这个类型继承自String,但是呢,从名字上我们就可以看出来这个类型,我们可以给字符串添加不同的属性,我们回到代码。这段代码的第二句我们通过:

   func addAttribute(name: String, value: AnyObject, range: NSRange)

这个函数给字符串添加了属性,这个API的第1、2个参数就是确定添加的属性类型,在这里我们添加的就是斜体这个属性,斜体这个属性的Value参数填写0~1之间的数值,在这个我们填写的是0.5.来看第二个参数,第二个参数是添加属性的范围,填写的是一个NSRange类型的值,应该不难理解。

以上代码段的功能就是给textview的字符串的第0个字符开始,连续五个字符添加斜体的效果。

是不是十分方便?~~~~~是的。

以上内容只是为了演示UITextView中的attributedText属性,事实上我们不需要这么做(感谢刘大大,告诉我接下来这种做法)。
在TextView中有一个属性叫做typingAttributes,xcode对这个属性的解释是这样的automatically resets when the selection changes,意思就是我们对这个属性进行设置可以改变接下来改变的文字。
也许这样说,不能让人太好的理解,我们在按钮中添加以下代码


@IBAction func Obliqueness(sender: AnyObject) {
textview.typingAttributes[NSObliquenessAttributeName] = (textview.typingAttributes[NSObliquenessAttributeName] as? NSNumber) == 0 ? 0.5 : 0
}

当** NSObliquenessAttributeName**的值为0时,点击按钮将将之改变为1,为1时则相反。我们点一下试试,神奇的事情发生啦啦啦啦~~~接下来我们输入的文字都变成了斜体。再次点击则变回正常。

以此类推,我们写出下划线、字体的增大以及减小的代码。


/**
字体减小

: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))

}
/**
设置斜体

:param: sender
*/
@IBAction func Obliqueness(sender: AnyObject) {
    textview.typingAttributes[NSObliquenessAttributeName] = (textview.typingAttributes[NSObliquenessAttributeName] as? NSNumber) == 0 ? 0.5 : 0
}
/**
设置下划线

:param: sender
*/
@IBAction func underline(sender: AnyObject) {
    self.textview.typingAttributes[NSUnderlineStyleAttributeName] =  (NSUnderlineStyle.StyleSingle.hashValue ) == 0 ? 1 : NSUnderlineStyle.StyleSingle.hashValue
}
/**

实现方法都是类似的,十分方便的已经实现了很多功能,这放在以前是不可能的(其实我不知道以前实现究竟有多复杂——!)。


2、插入图片。
前面我们知道TextView存在一个属性叫做attributedText,插入图片需要做的就是在TextView的这个属性中添加图片,上代码。


//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

  • 1、获取当前的attributedString
  • 2、新建一个NSTextAttachment,设置他的图片属性
  • 3、将刚刚创建的NSTextAttachment,添加在原本的attributedString的最后面
  • 4、重定义** textview.attributedText **

以上代码中出现一个变量img,这个变量就是从系统相册获取图片,代码如下:


@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为拍照、选择完进入图片编辑模式
imagePickerController.sourceType = sourceType
self.presentViewController(imagePickerController, animated: true, completion: {
})
}
}

首先是弹出一个alertView,让你进行选择,选择以后,将调用下面的方法,进入到相册进行选择图片。在这里你需要继承几个协议,不然在选择以后不会触发下面的方法:UIActionSheetDelegate,UIImagePickerControllerDelegate。同时进入相册你需要添加几个库:AssetsLibrary.framework和MobileCoreServices.framework。具体代码解释在这里就不行进解释,今天我们把重点放在富文本的实现上。当你选择图片以后,将促发以下方法,这也是前面添加的协议的功能。


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


同时在这个函数中我们给文本插入图片,插入方法在前面已经说过了。

当我们选择图片以后你会发现由于图片太大,所以在界面上只能显示一部分,那么我们就需要压缩图片,压缩方法如下:


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
}

这个方法将图片的宽度设置为屏幕的宽度,高度按比例缩放。

好的~~~~~我们终于实现了插入图片,其实在这里有一个很大的问题,就是下面这句话:


textview.attributedText = string

我们每次插入图片都将TextView的内容全部改变了一次,这样的做法,先不提在大量文字的情况下可能造成的卡顿问题,同时造成了编排问题,有同学可能已经发现了,当我们用这样的方法插入图片以后,当我们再次改变属性的时候,视图将会瞬间调到最上面,原因就是这句话。至于如何解决~~~~还没想到——!


3、选择字体
改变字体的方法其实和我们设置斜体,下划线等是一样的,方法如下:


func lovefont(sender:AnyObject){
self.textview.typingAttributes[NSFontAttributeName] = UIFont(name: "1-", size: (CGFloat)(self.fontSize))
}

那么我们现在的问题就是自定义字体了,毕竟xcode的字体大多不支持中文,同时中文显示的时候不那么优雅,我们要说的就是自定义字体。

加载自定义字体,并不是太过复杂,我在看到这篇文章描述加载自定义字体就感觉写的很好,http://www.jianshu.com/p/d728570bdf7b 小伙伴们有兴趣的话自行跳转过去看吧,这里就不重复介绍了。

4、制作长图片分享到微信朋友圈与微信好友。

那么我们需要做的第一步就是制作长图片,代码如下:


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
}

TextView继承自ScorllView,所以我们只需要给TextView进行截图,就可以制作一张长图片了,方法如上。然后我们需要做的就是调用微信给我们的API,将图片分享到朋友圈。

干货|swift,富文本编辑器_第2张图片
由于分享的话要申请AppId,所以在这里没有实现这个功能,不过实现的方法并不复杂。

微信分享的文档地址:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN

其实里头已经讲的很清楚了,有不明白的亲可以留言哦~


5、调用系统邮件发送文本

调用系统邮件,你可以将刚刚写好的文章或者啥的发送给好朋友,或者交给老师检查~~~~~~~首先我们还是得制作长图片,制作方法上面已经讲过了,就不重复累赘了,这里讲一下如何调用系统邮件。

首先你得继承一个协议:MFMailComposeViewControllerDelegate

然后代码如下:


@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()
}

代码就在上面了,自己感受一下的,解释不动了。
效果如下:

干货|swift,富文本编辑器_第3张图片
1.png

接下来也许会造个轮子,同时解决所有的BUG(至少我能发现的)。

代码已上传Github:https://github.com/superxlx/textDemo

亲们,自己下载代码感受一下,然后喜欢的换请点个喜欢同时关注一下我。

你可能感兴趣的:(干货|swift,富文本编辑器)