Automatically align text in UILabel according to text language

后端 未结 5 571
-上瘾入骨i
-上瘾入骨i 2021-02-04 19:59

I\'m interested in setting some text into a UILabel, and depending on the directionality of the language (e.g., Hebrew - right-to-left [RTL], English - left-to-righ

5条回答
  •  遥遥无期
    2021-02-04 20:39

    The ICU Project offers methods for what you are trying to achieve and on Xcode 11 it is possible to link the ICU library into an iOS application or iOS framework target. To do so, open your target and on the "General" tab under "Frameworks and Libraries" add libicucore.tbd.

    It might happen that Xcode chooses the macOS variant of the library if you do that in which case you'll see something like this in your project file.

    ABCDEFGHIJKLMNOPQRSTUVWX /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/lib/libicucore.tbd; sourceTree = DEVELOPER_DIR; };
    

    To force the iOS variant, simply edit the project file with a text editor to make the line look something like this

    ABCDEFGHIJKLMNOPQRSTUVWX /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = usr/lib/libicucore.tbd; sourceTree = SDKROOT; };
    

    Unfortunately, the version of the library that ships with iOS is a bit older and doesn't include ubidi_getBaseDirection. There is, however, a method u_charDirection that you can use to rebuilt ubidi_getBaseDirection. Simply walk the characters in the string and return the direction of the first character with strong directionality. Below is an example of how to do this in Swift (Objective-C port should be straightforward).

    enum Direction {
        case leftToRight
        case rightToLeft
        case neutral
    }
    
    func ubidi_getBaseDirection(of string: String) -> Direction {
        guard let data = string.data(using: .utf32) else {
            return .leftToRight
        }
        let chars = data.withUnsafeBytes { $0.bindMemory(to: UChar32.self) }
        for c in chars {
            let direction = u_charDirection(c)
            if direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC {
                return .rightToLeft
            } else if direction == U_LEFT_TO_RIGHT {
                return .leftToRight
            }
        }
        return .neutral
    }
    

    Note that since libicucore is a pure C library, you'll need to add it to your bridging header / umbrella header if you're working in Swift. I've found the following to be enough.

    #include "unicode/utypes.h"
    

提交回复
热议问题