在表情鍵盤的圖文混排中,會有很多細節問題。有的時候不理解其中的原因是很難改正的。本文主要是整理我遇到的各種問題及解決方案,供大家分享。如果你以前也遇到過類似的問題可以用我的方法修正了,希望能夠對博友們有所幫助。本文使用swift語言,OC的可能看不慣,但大多方法基本是一樣的就是語法不同。
上期回顧:關於微博編輯頁面添加表情鍵盤
如果你不是在董鉑然博客園看到本文,請點擊查看原文。
1.默認每添加一個表情是添加到最后,但是我們想添加到光標位置
默認做法(其中的str是通過點擊某個表情通過代理傳來的表情字符串)

// 會把用戶選擇的表情,拼接到最后!
textView.text = textView.text + (str ?? "")!
如果想插入到光標位置
// 在用戶光標位置插入表情文本
textView.replaceRange(textView.selectedTextRange!, withText: str!)
2.添加后的圖標大小不一樣。

解決方法:給所有的range設置一個統一的格式
// 設置整個屬性字符串中的文本屬性
let range = NSMakeRange(0, strM.length)
// 讓 可變的屬性文本 的字體 和 textView 的保持一致!
strM.addAttribute(NSFontAttributeName, value: textView.font, range: range)
3.因為前面用的是替換文本,所以在中間插入表情之后,光標會跳到段落末尾

解決方法:提前記錄光標的位置,然后在替換完文本位置之后再復原光標位置
在恢復光標的時候應該是location+1,如果不加1就是插入后光標在表情的前面
// 記錄光標位置 location 對應光標的位置
var location = textView.selectedRange.location
// 直接替換文本結果會導致光標移動到文本末尾
textView.attributedText = strM
// 重新設置光標位置
textView.selectedRange = NSMakeRange(location + 1, 0)
4.但是textView里顯示的是textView.AttrubuteText。富文本是對象無法直接發送出去。
解決方法:
①首先在每次點擊表情時把textView.AttrubuteText 打印出來 可以看到大批量的打印,輸出的是字典。區分后可以看出如果是表情,在字典里有NSAttachment的鍵值。而文本沒有
②通過以上那點的區別,遍歷這個大批量打印,打印出dict和Range,把所有的文本和表情都區分開

打印是:

③利用這個思路,寫一個textAttrubute的子類,並在這個方法中給表情對應的文本符號賦值,以后后來取用
import UIKit
class SXEmoteTextAttachment: NSTextAttachment {
// 表情對應的文本符號
var emoteString: String?
/// 返回一個 屬性字符串
class func attributeString(emoticon: Emoticon, height: CGFloat) -> NSAttributedString {
var attachment = SXEmoteTextAttachment()
attachment.image = UIImage(contentsOfFile: emoticon.imagePath!)
attachment.emoteString = emoticon.chs
// 設置高度
attachment.bounds = CGRectMake(0, -4, height, height)
// 2. 帶圖像的屬性文本
return NSAttributedString(attachment: attachment)
}
}
④在點擊某個圖片時,調用方法返回一個屬性字符串 ,在這一句調用.attributeString時已自動將表情轉化成文本符號
var attributeString = SXEmoteTextAttachment.attributeString(emoticon, height: font.lineHeight)
⑤定義一個result用於記錄拼接后的字符串
/// 返回文本框中轉換完成后的字符串 - (將表情圖片轉換成表情符號)
func fullText() -> String {
var result = String()
let textRange = NSMakeRange(0, attributedText.length)
attributedText.enumerateAttributesInRange(textRange, options: NSAttributedStringEnumerationOptions.allZeros, usingBlock: { (dict, range, _) -> Void in
if let attachment = dict["NSAttachment"] as? SXEmoteTextAttachment {
// 圖片
result += attachment.emoteString!
} else {
result += (self.attributedText.string as NSString).substringWithRange(range)
}
})
println("微博文本:\(result)")
return result
}
⑥最后就是在發微博的時候修改下參數,不是發textView.AttrubuteText 也不是發textView.text .而是發拼接后的
/// 發微博
@IBAction func sendStatus(sender: UIBarButtonItem) {
let urlString = "https://api.weibo.com/2/statuses/update.json"
if let token = AccessToken.loadAccessToken()?.access_token{
// 這里調用fullText方法 返回記錄並拼接后的
let params = ["access_token":token,"status":textView.fullText()]
let net = NetworkManager.sharedManager
net.requestJSON(.POST, urlString, params){ (result, error) -> () in
SVProgressHUD.showInfoWithStatus("微博發送成功")
self.dismissViewControllerAnimated(true, completion: nil)
}
}
}
⑦到此就完成了,編輯微博內顯示,和發送微博時的文本分開治理,互不沖突。
5.取消發布時,撰寫微博控制器快速就縮回了,回到了首頁鍵盤才緩慢縮回。

解決方法:
/// 取消按鈕點擊事件
@IBAction func cancel(sender: UIBarButtonItem) {
/// 為了更好的用戶體驗先縮鍵盤再縮文本框
self.textView.resignFirstResponder()
dismissViewControllerAnimated(true, completion: nil)
}
6.在輸入框中,表情和文字在水平方向上並不是對齊狀態,上下有差值

解決方法:微調
let height = textView.font.lineHeight
attachment.bounds = CGRectMake(0, -4, height, height)
7.只有在輸入文字時,placeholder和發送按鈕才會隱藏和點亮。點擊插入圖片時沒有反應

解決方法:手動讓用戶在輸入圖片時也調用代理方法
在圖片點擊代理方法emoticonsViewControllerDidSelectEmoticon里
// 手動調用代理方法 - 是否能夠插入文本
if textView(textView, shouldChangeTextInRange: textView.selectedRange, replacementText: str!) {
/// 設置輸入框的文字
if emoticon.chs != nil {
/// 從分類的方法中取
textView.setTextEmoticon(emoticon)
// 手動調用 didChage 方法
textViewDidChange(textView)
}else if emoticon.emoji != nil {
/// 默認是把表情拼接到最后, 用這行代碼是在光標位置插入文本
textView.replaceRange(textView.selectedTextRange!, withText: emoticon.emoji!)
}
}
其中的textViewDidChange 是用來控制按鈕狀態
func textViewDidChange(textView: UITextView) {
let fullText = self.textView.fullText()
self.textView.placeHolderLabel!.hidden = !fullText.isEmpty
sendButton.enabled = !fullText.isEmpty
}
8.在控制最大輸入數時一個表情如“[花心]” 占了8個字節
原來是
// 微博文字通常限制 140 個字
if textView.text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) + text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 140 {
return false
}
改成
// 微博文字通常限制 140 個字
if (self.textView.fullText() as NSString).length + (text as NSString).length > 140 {
return false
}
如果你不是在董鉑然博客園看到本文,請點擊查看原文。
歡迎關注!
