根据内容检测文本方向

Posted

技术标签:

【中文标题】根据内容检测文本方向【英文标题】:Detect text direction based on content 【发布时间】:2016-03-23 10:32:35 【问题描述】:

我想知道是否可以根据其内容动态设置UITextView的文本方向?

默认行为是这样的:如果您以 LTR 语言开始一行,则该行将是 LTR,但如果您以 RTL 语言开始下一行,则该行的方向将更改为 RTL。

我想要的是根据第一个设置整个段落的方向。

有可能吗?

【问题讨论】:

看看这里:***.com/questions/4905500/… 我想它会有所帮助。 【参考方案1】:

我自己也遇到过这个问题。通过一点点搜索,为 UITextView 制作了这个扩展,它检测第一个字母的语言并在需要时使其成为 RTL。 设置文本后需要调用该函数,所以可能需要在“UITextViewDelegate text change”方法中调用。

extension UITextView 
func detectRightToLeft() 
    if let text = self.text where !text.isEmpty 
        let tagschemes = NSArray(objects: NSLinguisticTagSchemeLanguage)
        let tagger = NSLinguisticTagger(tagSchemes: tagschemes as! [String], options: 0)
        tagger.string = text

        let language = tagger.tagAtIndex(0, scheme: NSLinguisticTagSchemeLanguage, tokenRange: nil, sentenceRange: nil)
        if language?.rangeOfString("he") != nil || language?.rangeOfString("ar") != nil || language?.rangeOfString("fa") != nil 
            self.text = text.stringByReplacingOccurrencesOfString("\n", withString: "\n")
            self.textAlignment = .Right
            self.makeTextWritingDirectionRightToLeft(nil)
        else
            self.textAlignment = .Left
            self.makeTextWritingDirectionLeftToRight(nil)
        
    


当然,这很混乱,并不完美。但它对我有用。你可以得到这个想法。

斯威夫特 3:

extension UITextView 
    func detectRightToLeft() 
        if let text = self.text, !text.isEmpty 
            let tagschemes = NSArray(objects: NSLinguisticTagSchemeLanguage)
            let tagger = NSLinguisticTagger(tagSchemes: tagschemes as! [String], options: 0)
            tagger.string = text

            let language = tagger.tag(at: 0, scheme: NSLinguisticTagSchemeLanguage, tokenRange: nil, sentenceRange: nil)
            if language?.range(of: "he") != nil || language?.range(of: "ar") != nil || language?.range(of: "fa") != nil 
                self.text = text.replacingOccurrences(of: "\n", with: "\n")
                self.textAlignment = .right
                self.makeTextWritingDirectionRightToLeft(nil)
            else
                self.textAlignment = .left
                self.makeTextWritingDirectionLeftToRight(nil)
            
        
    

【讨论】:

有时会导致崩溃 @Maysam 您能否提供更多有关崩溃情况的信息?此代码在我的应用程序中运行良好。 用空文本试试 @Maysam 这根本不应该发生! !text.isEmpty 就是为了这个。【参考方案2】:

根据 Ron 的回答,这里有一个更通用的字符串扩展

extension String 

    var isRTL: Bool 
        let cleanFile = self.replacingOccurrences(of: "\r", with: "\n")
        var newLineIndices: Array<Int> = []

        for (index, char) in cleanFile.enumerated() 
            if char == "\n" 
                newLineIndices.append(index)
            
        

        newLineIndices.insert(-1, at: 0)
        newLineIndices.append(cleanFile.count)

        let tagschemes = NSArray(objects: NSLinguisticTagScheme.language)
        let tagger = NSLinguisticTagger(tagSchemes: tagschemes as! [NSLinguisticTagScheme], options: 0)
        tagger.string = cleanFile

        for i in 0..<newLineIndices.count - 1 
            let language = tagger.tag(at: newLineIndices[i + 1] - 1, scheme: NSLinguisticTagScheme.language, tokenRange: nil, sentenceRange: nil)

            if String(describing: language).range(of: "he") != nil || String(describing: language).range(of: "ar") != nil || String(describing: language).range(of: "fa") != nil 
                return true
             else 
                return false
            
        

        return false
    

    var isLTR: Bool 
        let cleanFile = self.replacingOccurrences(of: "\r", with: "\n")
        var newLineIndices: Array<Int> = []

        for (index, char) in cleanFile.enumerated() 
            if char == "\n" 
                newLineIndices.append(index)
            
        

        newLineIndices.insert(-1, at: 0)
        newLineIndices.append(cleanFile.count)

        let tagschemes = NSArray(objects: NSLinguisticTagScheme.language)
        let tagger = NSLinguisticTagger(tagSchemes: tagschemes as! [NSLinguisticTagScheme], options: 0)
        tagger.string = cleanFile

        for i in 0..<newLineIndices.count - 1 
            let language = tagger.tag(at: newLineIndices[i + 1] - 1, scheme: NSLinguisticTagScheme.language, tokenRange: nil, sentenceRange: nil)

            if String(describing: language).range(of: "he") != nil || String(describing: language).range(of: "ar") != nil || String(describing: language).range(of: "fa") != nil 
                return false
             else 
                return true
            
        

        return false
    


【讨论】:

【参考方案3】:

基于 Arash R 的出色回答,这里有一个 Swift 4.2 扩展,它为 UITextView 中的每个段落单独选择文本方向。

它决定了每个段落中最后一个字符的语言。这样,如果您有一个 RTL 语言的编号列表,则该段落将是 RTL。

从文本更改方法调用该函数,如果您在第一次加载 ViewController 时填充 UITextView - 从 ViewDidLoad。

extension UITextView 
    func detectRightToLeft() 
        if let text = self.text, !text.isEmpty  // Set text, make sure it is not nil
            let cleanFile = text.replacingOccurrences(of: "\r", with: "\n")
            var newLineIndices:Array<Int> = []
            for (index, char) in cleanFile.enumerated() 
                if char == "\n" 
                    newLineIndices.append(index) // Get location of all newline characters
                
            
            newLineIndices.insert(-1, at: 0) // Place position 0 at the beginning of the array
            newLineIndices.append(cleanFile.count) // Add the location after last character

            let tagschemes = NSArray(objects: NSLinguisticTagScheme.language)
            let tagger = NSLinguisticTagger(tagSchemes: tagschemes as! [NSLinguisticTagScheme], options: 0)
            tagger.string = cleanFile

            for i in 0..<newLineIndices.count-1 
                // Determine direction by the last character of paragraph
                var taggerCounter = newLineIndices[i+1]-1
                var language = tagger.tag(at: taggerCounter, scheme: NSLinguisticTagScheme.language, tokenRange: nil, sentenceRange: nil)
                // Neutral characters should make the tagger look at the character before
                while language == nil && taggerCounter >= 1 
                    taggerCounter -= 1
                    language = tagger.tag(at: taggerCounter, scheme: NSLinguisticTagScheme.language, tokenRange: nil, sentenceRange: nil)
                

                if String(describing: language).range(of: "he") != nil || String(describing: language).range(of: "ar") != nil || String(describing: language).range(of: "fa") != nil 
                    self.setBaseWritingDirection(.rightToLeft, for: self.textRange(from: self.position(from: self.beginningOfDocument, offset: newLineIndices[i]+1)!, to: self.position(from: self.beginningOfDocument, offset: newLineIndices[i+1])!)!)
                    print ("Right to Left Paragraph at character \(newLineIndices[i]+1)")

                 else 
                    self.setBaseWritingDirection(.leftToRight, for: self.textRange(from: self.position(from: self.beginningOfDocument, offset: newLineIndices[i]+1)!, to: self.position(from: self.beginningOfDocument, offset: newLineIndices[i+1])!)!)
                    print ("Left to Right Paragraph at character \(newLineIndices[i]+1)")
                
            
        
    

编辑:以前的版本包括一个选项,可以通过段落的第一个字符进行选择。该选项导致崩溃,所以我暂时不考虑它。相反,当前代码包括对中性字符的处理。另一个编辑:将 taggerCounter 的最小值更改为 1,以防止它变成负数。

【讨论】:

以上是关于根据内容检测文本方向的主要内容,如果未能解决你的问题,请参考以下文章

使用Python,Tesseract更正文本方向

计算机视觉领域不同的方向:目标识别目标检测语义分割等

在 react-native 文本输入中检测粘贴事件

当内容在滚动时改变高度时如何检测滚动方向

内容安全使用腾讯云T-Sec天御对文本及图片内容进行安全检测

OpenCV实现基于傅里叶变换(FFT)的旋转文本校正(文字方向检测)