溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

iOS?UITextView如何實現(xiàn)類似微博的話題、提及用戶效果

發(fā)布時間:2022-06-07 15:25:02 來源:億速云 閱讀:129 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“iOS UITextView如何實現(xiàn)類似微博的話題、提及用戶效果”,在日常操作中,相信很多人在iOS UITextView如何實現(xiàn)類似微博的話題、提及用戶效果問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”iOS UITextView如何實現(xiàn)類似微博的話題、提及用戶效果”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

#話題#

最終效果是:

  • 編輯過程中#話題內(nèi)容#實時高亮

iOS?UITextView如何實現(xiàn)類似微博的話題、提及用戶效果

  • 高亮部分可以響應(yīng)點擊事件

iOS?UITextView如何實現(xiàn)類似微博的話題、提及用戶效果

1.高亮

基本思路是:使用正則匹配出成對的#,再利用UITextView的富文本實現(xiàn)高亮效果。

func refreshTopicStyle() {
        
        let regex = try! NSRegularExpression(pattern: "此處填寫正則表達(dá)式",
                                             options:[NSRegularExpression.Options.caseInsensitive])
        // 注意點
        let totalRange = NSMakeRange(0, (inputTextView.attributedText.string as NSString).length)
        let results = regex.matches(in: inputTextView.attributedText.string,
                                    options: NSRegularExpression.MatchingOptions.init(rawValue: 0),
                                    range: totalRange)
        let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: inputTextView.attributedText.string)
        attributedString.setAttributes(normalAttributes, range: totalRange)
        
        for result in results {
            attributedString.setAttributes(topicAttributes, range: result.range)
        }
        inputTextView.attributedText = attributedString
    }

這有一個注意點,計算 totalRange 前,先將 String 轉(zhuǎn)成了 NSString,這是因為此處 NSRange 中的 length 需要的是 UTF-16 長度,也就是與 NSString 的 length 定義一致,而 Swift 中的 String 沒有 length 只有 count,指的是字符數(shù),當(dāng)文本中出現(xiàn) emoji 表情時,二者就不一致了。

iOS?UITextView如何實現(xiàn)類似微博的話題、提及用戶效果

當(dāng)然,也有一些其他辦法來處理,如:

let lengthA = inputTextView.textStorage.length
let lengthB = inputTextView.attributedText.string.utf16.count

2.點擊事件

實現(xiàn)高亮部分的點擊事件,目前有3種實現(xiàn)方案:

  • 直接給UITextView添加點擊事件

  • 通過設(shè)置LinkAttribute,利用超文本鏈接的點擊實現(xiàn)

  • 重寫UITextViewtouches...方法

其中,第二種只限于在非編輯狀態(tài)(即 textView.isEditable = false)下的點擊,故排除,①、③均可,本文采用第一種,主要實現(xiàn)如下:

inputTextView.addTapGesture(self, handler: #selector(tapAttributedText(tap:)))
@objc private func tapAttributedText(tap: UITapGestureRecognizer) {
    guard tap.isKind(of: UITapGestureRecognizer.self), let textView = tap.view as? UITextView else {
        return
    }
    let layoutManager = textView.layoutManager
    var tapLocation = tap.location(in: textView)
    tapLocation.x -= textView.textContainerInset.left
    tapLocation.y -= textView.textContainerInset.top
    let characterIndex = layoutManager.characterIndex(for: tapLocation,
                                                      in: textView.textContainer,
                                                      fractionOfDistanceBetweenInsertionPoints: nil)
    for result in getCheckResult(format: Constants.TopicRegularExpression, text: inputTextView.attributedText.string) {
        if result.range.location < characterIndex, characterIndex < result.range.location + result.range.length {
            // 此處響應(yīng)點擊事件
            MBProgressHUD.showOnlyText(to: self.view, title: "美好時光")
            return
        }
    }
    inputTextView.becomeFirstResponder()
}

@提及用戶

  • 編輯過程中 @提及用戶 實時高亮,且只允許選取的用戶名高亮,手動輸入不高亮;

iOS?UITextView如何實現(xiàn)類似微博的話題、提及用戶效果

  • 點擊刪除鍵的時候,一次性刪除整個高亮部分

iOS?UITextView如何實現(xiàn)類似微博的話題、提及用戶效果

1.高亮

  • 記錄位置

本來準(zhǔn)備用正則匹配的,但因為只允許選取的用戶名高亮,純手動輸入的不高亮,所以使用正則匹配就不合理了,這里采用實時記錄、更新已選取用戶名位置的方式實現(xiàn)。

/// 用來保存已選取用戶信息的結(jié)構(gòu)體
struct UserInfo {
    /// 用戶名
    var userName: String
    /// 位置信息
    var range: NSRange
    /// 用于臨時替換的等長字符串
    var placeholder: String
}
  • 臨時替換

因為#話題#@提及用戶可以同時存在,所以需要考慮可能互相影響的問題,比如@提及用戶中間可能出現(xiàn)#,導(dǎo)致前后話題的正則匹配發(fā)生錯亂。

解決方案是:先使用一個@開頭且與@提及用戶等長的字符串替換@提及用戶,再執(zhí)行#話題#的正則匹配,最后再換回來。

2.整體刪除

刪除操作分為兩步:第一次點刪除僅選中整個用戶名(提醒用戶是整體刪除);第二次點刪除才真的刪除文本。

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text == "" {
        for (num, user) in usersArray.enumerated() { // usersArray 用于存放已選取的用戶信息
            // ②刪除選中的用戶名
            if textView.selectedRange.location <= user.range.location && NSMaxRange(user.range) <= NSMaxRange(textView.selectedRange) {
                textView.replace(textView.selectedTextRange ?? UITextRange(), withText: "")
                return false
            }
            // ①選中用戶名
            if textView.selectedRange.length == 0 && (textView.selectedRange.location == user.range.location + user.range.length) {
                textView.selectedRange = user.range
                return false
            }
        }
    }
}

到此,關(guān)于“iOS UITextView如何實現(xiàn)類似微博的話題、提及用戶效果”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI