以编程方式更改为从右到左的 RTL
Changing to right to left RTL programmatically
我正在开发一个支持两种语言的应用程序:英语和阿拉伯语。
当用户将语言更改为阿拉伯语时,我需要我的应用使文本从右到左 (RTL)。
我搜索了这个问题,发现 关于支持 RTL。
我想以编程方式应用上述答案,因为我需要在应用 运行.
时从 LTR 更改为 RTL
由于这是您自己的应用程序,我假设您可以控制它的 UI 个元素。
如果是这样,您不仅可以提供满足您要求的NSLayoutConstraint
,您还可以指定文本和按钮表示的对齐方式:NSTextAlignment
.
由于您无法以编程方式控制系统设置,请记住您的应用将不再利用自然约束,例如 leading
或 trailing
。
你介意我问你为什么需要这个吗?
我强烈建议您在执行此操作之前三思,主要是因为它提供了令人困惑的用户体验。用户希望他们的应用程序遵循系统语言,因此没有任何方法可以在应用程序内选择语言。
iOS 使您很容易以正确的方式做到这一点;如果您使用自动布局,在 UIKit API 上构建您的自定义控件并使用 NSLocalizedString,一切都会在运行时为您的用户做正确的事情。
我使用这个将我的应用更改为从右到左的 RTL :
self.transform = CGAffineTransformMakeScale(-1.0, 1.0)
这翻转了视图,然后我像这样翻转了视图中的对象:
label.transform = CGAffineTransformMakeScale(-1.0, 1.0)
textField.transform = CGAffineTransformMakeScale(-1.0, 1.0)
image.transform = CGAffineTransformMakeScale(-1.0, 1.0)
这使我的视图成为 RTL,而不是更改所有约束或将应用程序重新构建为 RTL。
当您需要阿拉伯语布局时,请在方法 didFinishLaunchingWithOptions 中使用以下几行,
对于 SWIFT
UIView.appearance().semanticContentAttribute = .forceRightToLeft
对于Objective C
[UIView 外观].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
并使用
重新加载应用
[self application:app didFinishLaunchingWithOptions:nil];
在 appDelegate 的其他一些方法中。在您要更改应用程序语言的地方调用该方法。
对应用程序的英文本地化,反之亦然。
在Swift 4试试这个,
//FOR RIGHT TO LEFT
UIView.appearance().semanticContentAttribute = .forceRightToLeft
//FOR LEFT TO RIGHT
UIView.appearance().semanticContentAttribute = .forceLeftToRight
03/05/2018:因为@SalmaGh 已经回答了他自己的问题。
但该解决方案会使您的 UI/UX 变得一团糟。
我会就如何解决这个问题提出建议。
这个答案是来自多个答案的参考,谁应该被赞成而不是反对。
Reason: Adding a language switcher to your app is only going to make it more confusing
此解决方案是必需的,因为一些 阿拉伯语 例如 @Afshin M. Khiabani 提到的是在应用程序中手动完成的,而不是Library/Framework/Device 默认。这使开发人员可以更好地控制他们的应用程序。然而这种方法并不受欢迎。
警告:这会弄乱带有子视图的水平滚动视图
但如果您必须强制 LTL 视图为 RTL。建议使用 IOSPercy 和 Jaydip 答案。但请做一个标记以供检查。例如 let isArabic = false
或使用 用户默认值。
首先在 AppDelegate 中输入代码 didFinishLaunchingWithOptions
为什么我们要把这个检查放在 AppDelegate 中是因为 AppDelegate 上的 UIView 将是所有视图控制器的超级视图。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.ChangeLayout()
return true
}
func ChangeLayout(){
var languageCode = ""
if let value = UserDefaults.standard.string(forKey: "Applanguage") {
languageCode = value
}else{
languageCode = ""
}
if(languageCode == "ar"){
UIView.appearance().semanticContentAttribute = .forceRightToLeft
}else{
UIView.appearance().semanticContentAttribute = .forceLeftToRight
}
}
如果 Applanguage 保存“ar”,此代码将自动以 RTL 模式加载应用程序,但是这只会在您重新打开应用程序时发生一次。
但是您可以通过调用 AppDelegate 函数来访问该函数,如下所示:
let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate
appDelegate?.ChangeLayout()
然后调用 TopMost ViewController 比如 LoadingScreen 之类的让 Reload 流程。
使用这行代码,它会在不关闭应用程序的情况下改变布局。从右到左
UIView.appearance().semanticContentAttribute = .forceRightToLeft
以及从左到右翻转
UIView.appearance().semanticContentAttribute = .forceLeftToRight
如果您想更改文本字段布局或文本更改,请使用此代码,因为我遇到过这个问题。 textfield 的文本不是 changning 布局。检查此代码以更改文本字段文本的布局
extension UITextField {
open override func awakeFromNib() {
super.awakeFromNib()
if UserDefaults.languageCode == "ar" {
if textAlignment == .natural {
self.textAlignment = .right
}
}
}
}
Swift 5 弃用
UIView.appearance().semanticContentAttribute = .forceRightToLeft
改用这个
self.view.semanticContentAttribute = .forceRightToLeft
在 UIView.semanticContentAttribute
贬值后更新。
swift 5
在 NSAttributed 字符串上同时对齐和右对齐或左对齐
let paragraphStyle = NSMutableParagraphStyle()
if(arabic){
paragraphStyle.alignment = .justified
paragraphStyle.baseWritingDirection = .rightToLeft
}else{
paragraphStyle.alignment = .justified
paragraphStyle.baseWritingDirection = .leftToRight
}
//有效
UIView.appearance().semanticContentAttribute = .forceRightToLeft
UIView.appearance().semanticContentAttribute = .forceLeftToRight
Swift 5 位场景代表
我创建了一个简单的单例 class 可以使用 Localizable.strings 文件动态切换语言,它还将替换 keyWindow 的 rootViewController 并充当 AppRestart,以供详细实施我写了一篇文章You can read it here
//
// AppLanguage.swift
// Created by Mohamad Kaakati on 30/05/2021.
//
import UIKit
enum Languages {
case english, arabic, french
}
class AppLanguage {
static let shared = AppLanguage()
private init() { }
var bundle: Bundle?
func set(index: Languages) {
switch index {
case .english:
// For English Language set LTR
print("Set language to LTR")
selectBundleForResource(forResource: "en", isRTL: false)
case .arabic:
// For RTL Language set RTL
print("Set language to RTL.")
selectBundleForResource(forResource: "ar", isRTL: true)
default:
// For French Language set LTR
selectBundleForResource(forResource: "fr", isRTL: false)
}
}
private func selectBundleForResource(forResource: String!, isRTL: Bool) {
guard let path = Bundle.main.path(forResource: forResource, ofType: "lproj") else {
return
}
self.bundle = Bundle.init(path: path)
switchViewControllers(isRTL: isRTL)
}
private func setKeyWindowFromAppDelegate(isRTL: Bool) {
UIView.appearance().semanticContentAttribute = isRTL ? .forceRightToLeft : .forceLeftToRight
let appDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate
let homeViewController = UIViewController() // Replace with your root view controller.
appDelegate?.window?.rootViewController = homeViewController
}
private func switchViewControllers(isRTL rtl : Bool){
if rtl {
setKeyWindowFromAppDelegate(isRTL: true)
} else {
setKeyWindowFromAppDelegate(isRTL: false)
}
}
}
public extension String {
/// Return Localized String
var localizedString : String {
get {
return self.toLocal()
}
}
}
private extension String {
func toLocal() -> String {
if AppLanguage.shared.bundle != nil {
return NSLocalizedString(self, tableName: "Localizable", bundle: AppLanguage.shared.bundle!, value: "", comment: "")
}
return self
}
}
您可以使用以下方法设置语言:
AppLanguage.shared.set(index: .arabic)
我正在开发一个支持两种语言的应用程序:英语和阿拉伯语。 当用户将语言更改为阿拉伯语时,我需要我的应用使文本从右到左 (RTL)。
我搜索了这个问题,发现
我想以编程方式应用上述答案,因为我需要在应用 运行.
时从 LTR 更改为 RTL由于这是您自己的应用程序,我假设您可以控制它的 UI 个元素。
如果是这样,您不仅可以提供满足您要求的NSLayoutConstraint
,您还可以指定文本和按钮表示的对齐方式:NSTextAlignment
.
由于您无法以编程方式控制系统设置,请记住您的应用将不再利用自然约束,例如 leading
或 trailing
。
你介意我问你为什么需要这个吗?
我强烈建议您在执行此操作之前三思,主要是因为它提供了令人困惑的用户体验。用户希望他们的应用程序遵循系统语言,因此没有任何方法可以在应用程序内选择语言。
iOS 使您很容易以正确的方式做到这一点;如果您使用自动布局,在 UIKit API 上构建您的自定义控件并使用 NSLocalizedString,一切都会在运行时为您的用户做正确的事情。
我使用这个将我的应用更改为从右到左的 RTL :
self.transform = CGAffineTransformMakeScale(-1.0, 1.0)
这翻转了视图,然后我像这样翻转了视图中的对象:
label.transform = CGAffineTransformMakeScale(-1.0, 1.0)
textField.transform = CGAffineTransformMakeScale(-1.0, 1.0)
image.transform = CGAffineTransformMakeScale(-1.0, 1.0)
这使我的视图成为 RTL,而不是更改所有约束或将应用程序重新构建为 RTL。
当您需要阿拉伯语布局时,请在方法 didFinishLaunchingWithOptions 中使用以下几行, 对于 SWIFT
UIView.appearance().semanticContentAttribute = .forceRightToLeft
对于Objective C
[UIView 外观].semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
并使用
重新加载应用[self application:app didFinishLaunchingWithOptions:nil];
在 appDelegate 的其他一些方法中。在您要更改应用程序语言的地方调用该方法。
对应用程序的英文本地化,反之亦然。
在Swift 4试试这个,
//FOR RIGHT TO LEFT
UIView.appearance().semanticContentAttribute = .forceRightToLeft
//FOR LEFT TO RIGHT
UIView.appearance().semanticContentAttribute = .forceLeftToRight
03/05/2018:因为@SalmaGh 已经回答了他自己的问题。
但该解决方案会使您的 UI/UX 变得一团糟。
我会就如何解决这个问题提出建议。
这个答案是来自多个答案的参考,谁应该被赞成而不是反对。
Reason: Adding a language switcher to your app is only going to make it more confusing
此解决方案是必需的,因为一些 阿拉伯语 例如 @Afshin M. Khiabani 提到的是在应用程序中手动完成的,而不是Library/Framework/Device 默认。这使开发人员可以更好地控制他们的应用程序。然而这种方法并不受欢迎。
警告:这会弄乱带有子视图的水平滚动视图
但如果您必须强制 LTL 视图为 RTL。建议使用 IOSPercy 和 Jaydip 答案。但请做一个标记以供检查。例如 let isArabic = false
或使用 用户默认值。
首先在 AppDelegate 中输入代码 didFinishLaunchingWithOptions
为什么我们要把这个检查放在 AppDelegate 中是因为 AppDelegate 上的 UIView 将是所有视图控制器的超级视图。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.ChangeLayout()
return true
}
func ChangeLayout(){
var languageCode = ""
if let value = UserDefaults.standard.string(forKey: "Applanguage") {
languageCode = value
}else{
languageCode = ""
}
if(languageCode == "ar"){
UIView.appearance().semanticContentAttribute = .forceRightToLeft
}else{
UIView.appearance().semanticContentAttribute = .forceLeftToRight
}
}
如果 Applanguage 保存“ar”,此代码将自动以 RTL 模式加载应用程序,但是这只会在您重新打开应用程序时发生一次。
但是您可以通过调用 AppDelegate 函数来访问该函数,如下所示:
let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate
appDelegate?.ChangeLayout()
然后调用 TopMost ViewController 比如 LoadingScreen 之类的让 Reload 流程。
使用这行代码,它会在不关闭应用程序的情况下改变布局。从右到左
UIView.appearance().semanticContentAttribute = .forceRightToLeft
以及从左到右翻转
UIView.appearance().semanticContentAttribute = .forceLeftToRight
如果您想更改文本字段布局或文本更改,请使用此代码,因为我遇到过这个问题。 textfield 的文本不是 changning 布局。检查此代码以更改文本字段文本的布局
extension UITextField {
open override func awakeFromNib() {
super.awakeFromNib()
if UserDefaults.languageCode == "ar" {
if textAlignment == .natural {
self.textAlignment = .right
}
}
}
}
Swift 5 弃用
UIView.appearance().semanticContentAttribute = .forceRightToLeft
改用这个
self.view.semanticContentAttribute = .forceRightToLeft
在 UIView.semanticContentAttribute
贬值后更新。
swift 5
在 NSAttributed 字符串上同时对齐和右对齐或左对齐
let paragraphStyle = NSMutableParagraphStyle()
if(arabic){
paragraphStyle.alignment = .justified
paragraphStyle.baseWritingDirection = .rightToLeft
}else{
paragraphStyle.alignment = .justified
paragraphStyle.baseWritingDirection = .leftToRight
}
//有效
UIView.appearance().semanticContentAttribute = .forceRightToLeft
UIView.appearance().semanticContentAttribute = .forceLeftToRight
Swift 5 位场景代表
我创建了一个简单的单例 class 可以使用 Localizable.strings 文件动态切换语言,它还将替换 keyWindow 的 rootViewController 并充当 AppRestart,以供详细实施我写了一篇文章You can read it here
//
// AppLanguage.swift
// Created by Mohamad Kaakati on 30/05/2021.
//
import UIKit
enum Languages {
case english, arabic, french
}
class AppLanguage {
static let shared = AppLanguage()
private init() { }
var bundle: Bundle?
func set(index: Languages) {
switch index {
case .english:
// For English Language set LTR
print("Set language to LTR")
selectBundleForResource(forResource: "en", isRTL: false)
case .arabic:
// For RTL Language set RTL
print("Set language to RTL.")
selectBundleForResource(forResource: "ar", isRTL: true)
default:
// For French Language set LTR
selectBundleForResource(forResource: "fr", isRTL: false)
}
}
private func selectBundleForResource(forResource: String!, isRTL: Bool) {
guard let path = Bundle.main.path(forResource: forResource, ofType: "lproj") else {
return
}
self.bundle = Bundle.init(path: path)
switchViewControllers(isRTL: isRTL)
}
private func setKeyWindowFromAppDelegate(isRTL: Bool) {
UIView.appearance().semanticContentAttribute = isRTL ? .forceRightToLeft : .forceLeftToRight
let appDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate
let homeViewController = UIViewController() // Replace with your root view controller.
appDelegate?.window?.rootViewController = homeViewController
}
private func switchViewControllers(isRTL rtl : Bool){
if rtl {
setKeyWindowFromAppDelegate(isRTL: true)
} else {
setKeyWindowFromAppDelegate(isRTL: false)
}
}
}
public extension String {
/// Return Localized String
var localizedString : String {
get {
return self.toLocal()
}
}
}
private extension String {
func toLocal() -> String {
if AppLanguage.shared.bundle != nil {
return NSLocalizedString(self, tableName: "Localizable", bundle: AppLanguage.shared.bundle!, value: "", comment: "")
}
return self
}
}
您可以使用以下方法设置语言:
AppLanguage.shared.set(index: .arabic)