iPhone:如何以编程方式更改键盘语言

45
我试图在我的 iOS 5.x 应用程序中为原生键盘打开时提供不同的语言支持。请问有人可以指导我如何通过编程方式在原生键盘中添加该语言支持吗?我看到了 Carbon 框架,但是好像只适用于 Mac 应用程序。
谢谢。

1
@Getsym,请更新所选解决方案。 - Iulian Onofrei
7个回答

48

从iOS 7开始,您可以根据每个UIResponder的基础来执行此操作。在UIResponder类中有一个名为textInputMode的属性。它是只读的,但文档中表示:

文本输入模式标识了当此响应者处于活动状态时显示的语言和键盘。

对于响应者,系统通常会显示基于用户语言偏好的键盘。您可以重新定义此属性,并在需要响应者使用特定键盘的情况下使用它来返回不同的文本输入模式。用户仍然可以在响应者处于活动状态时更改键盘,但切换到另一个响应者然后再切换回来会恢复您指定的键盘。

在我的项目中,我创建了一个UITextField的子类,并定义了一个名为userDefinedKeyboardLanguage的新属性。我还覆盖了上面提到的textInputMode方法。它看起来类似于以下内容:

- (UITextInputMode *) textInputMode {
    for (UITextInputMode *tim in [UITextInputMode activeInputModes]) {
        if ([[Utilities langFromLocale:userDefinedKeyboardLanguage] isEqualToString:[Utilities langFromLocale:tim.primaryLanguage]]) return tim;
    }
    return [super textInputMode];
}

我在我的Utilities类中还有一个自定义的方法+(NSString *)langFromLocale:(NSString *)locale,它的样子是这样的:

+ (NSString *)langFromLocale:(NSString *)locale {
    NSRange r = [locale rangeOfString:@"_"];
    if (r.length == 0) r.location = locale.length;
    NSRange r2 = [locale rangeOfString:@"-"];
    if (r2.length == 0) r2.location = locale.length;
    return [[locale substringToIndex:MIN(r.location, r2.location)] lowercaseString];
}
现在我的自定义文本框类可以通过设置userDefinedKeyboardLanguage属性来简单地更改键盘输入语言为所需的语言。

现在我的自定义文本框类可以通过设置userDefinedKeyboardLanguage属性来简单地更改键盘输入语言为所需的语言。


3
好的!这应该就是答案了。 - crisisGriega
2
我的项目是用Swift编写的,但我发现我需要回退到ObjC来覆盖textInputMode。 - Chris
3
如何在Swift中覆盖textInputMode? - Hoven
1
这绝对应该是答案。 - evalsyrelec
1
太棒了。但是有一个问题(不是你的错)。如果用户将键盘切换到另一种语言,键盘语言仍然会错误地报告为“tim”语言。 - matt
显示剩余4条评论

43

我知道这是一个老问题,但这是我改变键盘语言的方法。

感谢 @the4kman 的提醒:这种方法只能将当前键盘更改为在设置中添加过的键盘。

Swift 3:

class CustomTextField: UITextField {

    private func getKeyboardLanguage() -> String? {
        return "en" // here you can choose keyboard any way you need
    }

    override var textInputMode: UITextInputMode? {
        if let language = getKeyboardLanguage() {
            for tim in UITextInputMode.activeInputModes {
                if tim.primaryLanguage!.contains(language) {
                    return tim
                }
            }
        }
        return super.textInputMode
    }

}

3
哇,我没想到这是可能的,但它可以运行。iOS 10,Xcode 8,Swift 3。 - Trevis Thomas
3
请注意,这只能将键盘更改为用户在设置中添加的那些。 - Tamás Sengel
感谢@kotvaska提供的解决方案。我发现一个问题,键盘不能立即切换到另一种语言。但是在键盘上单击后,它会切换到覆盖的语言。 - Bill Chan
2
自iOS 13起,此方法已不再适用(键盘忽略textInputMode返回值)。我认为你只能使用它来切换到英文键盘,但不能做其他事情。目前还不清楚这是一个错误还是一个“新功能”。建议大家都提交反馈。 - dbquarrel
3
@dbquarrel 我刚试了一下,在iOS 13.3上无法使用,即使是切换到英文键盘也不行。 - alobaili
显示剩余6条评论

7
抱歉,这是不可能的 - 用户只能在设置中更改语言。但是如果您愿意(或询问用户的偏好),您可以为用户提供“英文”键盘。使用UIKeyboardTypeASCIICapable可以实现此功能。您可以通过按底部行上的“地球图标”直接在键盘上更改键盘。首先,您必须在设置中启用这些输入语言。然后按键盘上的地球按钮可以在这些语言之间切换。

你好,那么,最新的SDK也不能以编程方式允许更改键盘语言到不同的语言吗?如果需要在我的应用程序中显示键盘,我只能显示英语键盘吗?您能否提供任何苹果链接,说明这是不可能的,这样我就可以更清楚地阅读,非常感谢。 - Getsy
我看到iPhone的键盘设置中有一个“添加新键盘”的选项。我们不能通过我们的程序或iTunes同步将自己的语言文件安装到其中吗? - Getsy
是的,我们不能插入自己的语言。 - Nimit Parekh
2
也许在2012年还不可能。现在通过覆盖“textInputMode”,它是可能的。请参见kotvaska的答案。它甚至适用于iOS 11 :) - nacho4d
2012年时还不可能,后来通过覆盖textInputMode才实现了。但是截至2019年9月,iOS 13已经忽略了textInputMode的返回值。 - dbquarrel

6

声明:

@IBOutlet var yourTextField:cTextField!;

使用:

yourTextField.languageCode = "ru";

类 cTextField:

class cTextField: UITextField {

    // ru, en, ....
    var languageCode:String?{
        didSet{
            if self.isFirstResponder{
                self.resignFirstResponder();
                self.becomeFirstResponder();
            }
        }
    }

    override var textInputMode: UITextInputMode?{
        if let language_code = self.languageCode{
            for keyboard in UITextInputMode.activeInputModes{
                if let language = keyboard.primaryLanguage{
                    let locale = Locale.init(identifier: language);
                    if locale.languageCode == language_code{
                        return keyboard;
                    }
                }
            }
        }
        return super.textInputMode;
    }
}

1
这个可以工作,但我不能使用它,因为我必须将所有的UITextFields更改为新的cTextField。我想要一些扩展现有的UITextField。 - Vakas
这是截至2023年6月在iOS 16上对我有效的唯一工作解决方案。 - Joseph

6
所有答案都很好。但是在Swift中,您可以在扩展中重写在父类中定义的方法和变量(UIResponder),因此不需要子类化。使用更具Swift风格的一行代码替换for循环也很好。
public extension UITextField {  
    override var textInputMode: UITextInputMode? {
        return UITextInputMode.activeInputModes.filter { $0.primaryLanguage == "emoji" }.first ?? super.textInputMode
    }
}

与其使用“emoji”,可以考虑使用Utils.currentAppLanguage


6

Swift 5 的实现:

public extension UITextField 
{ 
    // ⚠️ Prefer english keyboards
    //
    override var textInputMode: UITextInputMode?
    {
        let locale = Locale(identifier: "en_US") // your preferred locale

        return
            UITextInputMode.activeInputModes.first(where: { $0.primaryLanguage == locale.languageCode })
            ??
            super.textInputMode
    }
}

我用了这个解决方案,但它没有起作用。我的应用程序有小数类型的键盘,用于输入浮点值,当我选择英语时,它可以很好地使用并显示小数点,但是无论我选择德语还是法语,小数点都不应该变成逗号,但这并没有发生,即使我将textInputMode设置为德语或法语也是如此。 - Ashvini
如果我关闭并重新启动我的应用程序,那么小数点会被反映为逗号。不确定这是什么问题。 - Ashvini

3
这似乎可以用来更改键盘,例如到希腊语键盘:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"el", nil] 
    forKey:@"AppleLanguages"]; 

[[NSUserDefaults standardUserDefaults] synchronize]; 

2
这还能用吗?我正在尝试使用iOS 7,但似乎无法更改键盘,它仍然是英文。 - Jonas Stawski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接