专业java、php、iOS、C++、网页设计、平面设计、网络营销、游戏开发、前端与移动开发培训机构
插入emoji和图片到textView
当点击表情的时候需要将表情插入到
textVew中.需要知道点击的是那个表情,在CZEmoticonPageCell创建按钮的时候给按钮添加点击事件/** 添加20个表情按钮到cell里面 */ private func addEmoticonButtons() { for _ in 0..<HMEmoticonNumberOfPage { // 创建按钮 let button = HMEmoticonButton() button.backgroundColor = UIColor.random button.addTarget(self, action: #selector(didClickEmoticonButton(button:)), for: UIControlEvents.touchUpInside) // 按钮添加到contentView contentView.addSubview(button) // 将按钮添加到数组,方便后面遍历按钮 emoticonButtons.append(button) } } /** 按钮点击事件 parameter emoticonButton: 被点击的按钮 */ @objc private func didClickEmoticonButton(button: HMEmoticonButton) { print("点击了: \(button)") }- 目前是在
HMEmoticonPageCell里面响应点击事件,需要将点击事件传递给HMEmoticonKeyboard, 使用代理来实现,在HMEmoticonPageCell定义HMEmoticonPageCellDelegateprotocol HMEmoticonPageCellDelegate: NSObjectProtocol { /// 表情按钮点击的代理事件 func emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel) } - 在
HMEmoticonPageCell定义delegate属性/// 代理 weak var delegate: HMEmoticonPageCellDelegate? - 在
HMEmoticonPageCell的按钮点击方法didClickEmoticonButton中调用代理的emoticonKeyboardPageCell:didSelectedEmoticon:/** 按钮点击事件 parameter emoticonButton: 被点击的按钮 */ @objc private func didClickEmoticonButton(button: HMEmoticonButton) { // print("点击了: \(button)") delegate?.emoticonPageCell(didSelectedEmoticon: button.emoticon!) } 在
HMEmoticonKeyboard的cellForItemAtIndexPath设置self为cell的代理// 返回cell func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! HMEmoticonPageCell // 设置为cell的代理 cell.delegate = self cell.indexPath = indexPath cell.pageEmoticons = HMEmoticonManager.shared.packages[indexPath.section].pageEmoticons[indexPath.item] return cell }- 让
HMEmoticonKeyboard实现HMEmoticonPageCellDelegate// MARK: - 扩展 HMEmoticonKeyboard 实现 HMEmoticonPageCellDelegate 协议 extension HMEmoticonKeyboard: HMEmoticonPageCellDelegate { func emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel) { print("我在keyboard里面知道了cell点击了表情: \(emoticon)") } } - 至此,在
HMEmoticonKeyboard就能响应表情按钮的点击事件了 - 插入
emoji和图片到textView其实就是修改textView的text,所以HMEmoticonKeyboard需要拥有textView- 在
HMEmoticonKeyboard定义textView属性/// textView weak var textView: UITextView? - 在
ViewController创建HMEmoticonKeyboard的时候设置textView
- 在
- 插入
emoji表情 在
HMEmoticonKeyboard定义insertEmoticon方法来 插入表情到textViewextension HMEmoticonKeyboard: HMEmoticonPageCellDelegate { func emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel) { insertEmoticon(emoticon: emoticon) } /** 插入表情到textView parameter emoticon: 表情模型 */ func insertEmoticon(emoticon: HMEmoticonModel) { // 判断textView是否有值 guard let textView = self.textView else { print("textView 为空") return } // 插入emoji if let emoji = emoticon.emoji { textView.insertText(emoji) print("插入emoji: \(textView.text)") } } }- 运行,可以添加
emoji表情了 插入
图片到textView,要将图片添加到textView需要使用附件NSTextAttachment, 在HMEmoticonKeyboard的insertEmoticon将图片添加到textView/** 插入表情到textView parameter emoticon: 表情模型 */ func insertEmoticon(emoticon: HMEmoticonModel) { // 判断textView是否有值 guard let textView = self.textView else { print("textView 为空") return } // 插入emoji if let emoji = emoticon.emoji { textView.insertText(emoji) return } // 插入表情图片,需要使用到属性文本 if let pngPath = emoticon.fullPngPath { // 附件,图片可以作为附件,附件可以添加到属性文本 let attachment = NSTextAttachment() attachment.image = UIImage(contentsOfFile: pngPath) let attrString = NSAttributedString(attachment: attachment) textView.attributedText = attrString } }运行,可以添加图片到
textView但是发现文字没有了.不能直接将现有文本给覆盖了.需要获取到textView现有text,将附件替换到光标的位置// 插入表情图片,需要使用到属性文本 if let pngPath = emoticon.fullPngPath { // 附件,图片可以作为附件,附件可以添加到属性文本 let attachment = NSTextAttachment() attachment.image = UIImage(contentsOfFile: pngPath) // 创建带附件的属性文本 let attrString = NSAttributedString(attachment: attachment) // 获取textView现有文本 let attrStringM = NSMutableAttributedString(attributedString: textView.attributedText) // 替换属性文本到对应的位置 attrStringM.replaceCharacters(in: textView.selectedRange, with: attrString) // 将属性文本设置给textView textView.attributedText = attrStringM }插入图片后光标跑到最后面位置,先记录下光标位置,在赋值属性文本后重新设置光标位置
// 插入表情图片,需要使用到属性文本 if let pngPath = emoticon.fullPngPath { // 附件,图片可以作为附件,附件可以添加到属性文本 let attachment = NSTextAttachment() attachment.image = UIImage(contentsOfFile: pngPath) // 创建带附件的属性文本 let attrString = NSAttributedString(attachment: attachment) // 获取textView现有文本 let attrStringM = NSMutableAttributedString(attributedString: textView.attributedText) // 光标位置 let oldSelectedRange = textView.selectedRange // 替换属性文本到对应的位置 attrStringM.replaceCharacters(in: oldSelectedRange, with: attrString) // 将属性文本设置给textView textView.attributedText = attrStringM // 重新设置光标位置 textView.selectedRange = NSRange(location: oldSelectedRange.location + 1, length: 0) }直接添加到
textView的图片比较大,需要设置图片的大小// 插入表情图片,需要使用到属性文本 if let pngPath = emoticon.fullPngPath { // 附件,图片可以作为附件,附件可以添加到属性文本 let attachment = NSTextAttachment() attachment.image = UIImage(contentsOfFile: pngPath) // 获取文本的高度 let height = textView.font?.lineHeight ?? 10 // 设置附件的大小 attachment.bounds = CGRect(x: 0, y: -4, width: height, height: height) // 创建带附件的属性文本 let attrString = NSAttributedString(attachment: attachment) // 获取textView现有文本 let attrStringM = NSMutableAttributedString(attributedString: textView.attributedText) // 光标位置 let oldSelectedRange = textView.selectedRange // 替换属性文本到对应的位置 attrStringM.replaceCharacters(in: oldSelectedRange, with: attrString) // 将属性文本设置给textView textView.attributedText = attrStringM // 重新设置光标位置 textView.selectedRange = NSRange(location: oldSelectedRange.location + 1, length: 0) }在表情图片后面在插入一张表情会发现表情图片变小了.原因是附件没有
font属性,在通过附件创建属性文本的时候设置属性文本的font// 插入表情图片,需要使用到属性文本 if let pngPath = emoticon.fullPngPath { // 附件,图片可以作为附件,附件可以添加到属性文本 let attachment = NSTextAttachment() attachment.image = UIImage(contentsOfFile: pngPath) // 获取文本的高度 let height = textView.font?.lineHeight ?? 10 // 设置附件的大小 attachment.bounds = CGRect(x: 0, y: -4, width: height, height: height) // 创建带附件的属性文本,并且添加font属性 let attrString = NSMutableAttributedString(attributedString: NSAttributedString(attachment: attachment)) attrString.addAttribute(NSFontAttributeName, value: textView.font!, range: NSRange(location: 0, length: 1)) // 获取textView现有文本 let attrStringM = NSMutableAttributedString(attributedString: textView.attributedText) // 光标位置 let oldSelectedRange = textView.selectedRange // 替换属性文本到对应的位置 attrStringM.replaceCharacters(in: oldSelectedRange, with: attrString) // 将属性文本设置给textView textView.attributedText = attrStringM // 重新设置光标位置 textView.selectedRange = NSRange(location: oldSelectedRange.location + 1, length: 0) }- 至此,添加图片到
textView上面就好了
实现删除按钮删除 textView 的文字和表情
在
HMEmoticonPageCellDelegate添加点击了删除按钮的协议方法emoticonPageCellDidClickDeleteButtonprotocol HMEmoticonPageCellDelegate: NSObjectProtocol { /// 表情按钮点击的代理事件 func emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel) /// 删除按钮点击的代理事件 func emoticonPageCellDidClickDeleteButton() }在
HMEmoticonPageCell的deleteButton懒加载里面添加点击事件/// 删除按钮 private lazy var deleteButton: UIButton = { let button = UIButton() button.setImage(UIImage(named: "compose_emotion_delete"), for: UIControlState.normal) button.setImage(UIImage(named: "compose_emotion_delete_highlighted"), for: UIControlState.highlighted) button.addTarget(self, action: #selector(didClickdeleteButton), for: .touchUpInside) return button }()/// 删除按钮点击事件 func didClickdeleteButton() -> Void { delegate?.emoticonPageCellDidClickDeleteButton() }在
HMEmoticonKeyboard实现HMEmoticonPageCellDelegate协议的deleteButtonClick方法中删除textView的文字extension HMEmoticonKeyboard: HMEmoticonPageCellDelegate { func emoticonPageCellDidClickDeleteButton() { textView?.deleteBackward() } func emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel) { insertEmoticon(emoticon: emoticon) } ... }