Skip to content

Commit

Permalink
feat: change keyboard language
Browse files Browse the repository at this point in the history
  • Loading branch information
mopsicus committed Sep 10, 2024
1 parent d9af197 commit bf78600
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 8 deletions.
74 changes: 70 additions & 4 deletions Android~/plugin/src/main/java/com/mopsicus/umi/MobileInput.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.mopsicus.umi;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PorterDuff;
Expand All @@ -10,6 +11,7 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build;
import android.os.LocaleList;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
Expand All @@ -30,6 +32,10 @@
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

public class MobileInput {

Expand All @@ -46,6 +52,7 @@ public class MobileInput {
private static final String ON_FOCUS = "ON_FOCUS";
private static final String ON_UNFOCUS = "ON_UNFOCUS";
private static final String SET_VISIBLE = "SET_VISIBLE";
private static final String SET_LANGUAGE = "SET_LANGUAGE";
private static final String TEXT_CHANGE = "TEXT_CHANGE";
private static final String TEXT_END_EDIT = "TEXT_END_EDIT";
private static final String ANDROID_KEY_DOWN = "ANDROID_KEY_DOWN";
Expand Down Expand Up @@ -198,6 +205,10 @@ private void processData(JSONObject data) {
boolean isVisible = data.getBoolean("is_visible");
this.SetVisible(isVisible);
break;
case SET_LANGUAGE:
String code = data.getString("value");
setKeyboardLanguage(code);
break;
case ANDROID_KEY_DOWN:
String strKey = data.getString("key");
this.OnForceAndroidKeyDown(strKey);
Expand Down Expand Up @@ -285,6 +296,7 @@ private void Create(int id, JSONObject data) {
String contentType = data.getString("content_type");
String inputType = data.optString("input_type");
String keyboardType = data.optString("keyboard_type");
String keyboardLanguage = data.optString("keyboard_language");
String returnKeyType = data.getString("return_key_type");
String alignment = data.getString("align");
String customFont = data.getString("font");
Expand Down Expand Up @@ -417,6 +429,9 @@ private void Create(int id, JSONObject data) {
} else {
edit.setTypeface(Typeface.SANS_SERIF);
}
if (!keyboardLanguage.equals("default")) {
setKeyboardLanguage(keyboardLanguage);
}
final MobileInput input = this;
edit.setOnFocusChangeListener((v, isFocus) -> {
if (!isFocus) {
Expand Down Expand Up @@ -517,25 +532,33 @@ void setCaretColor(int color) {
InsetDrawable insetDrawable = (InsetDrawable) edit.getTextCursorDrawable();
insetDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
edit.setTextCursorDrawable(insetDrawable);
Log.d("[UMI]", String.format("set caret cursor: %s", color));
if (Plugin.bridge.isDebug) {
Log.d("[UMI]", String.format("set caret cursor: %s", color));
}
}
if (edit.getTextSelectHandle() instanceof BitmapDrawable) {
BitmapDrawable insetDrawable = (BitmapDrawable) edit.getTextSelectHandle();
insetDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
edit.setTextSelectHandle(insetDrawable);
Log.d("[UMI]", String.format("set caret handle: %s", color));
if (Plugin.bridge.isDebug) {
Log.d("[UMI]", String.format("set caret handle: %s", color));
}
}
if (edit.getTextSelectHandleRight() instanceof BitmapDrawable) {
BitmapDrawable insetDrawable = (BitmapDrawable) edit.getTextSelectHandleRight();
insetDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
edit.setTextSelectHandleRight(insetDrawable);
Log.d("[UMI]", String.format("set caret handle right: %s", color));
if (Plugin.bridge.isDebug) {
Log.d("[UMI]", String.format("set caret handle right: %s", color));
}
}
if (edit.getTextSelectHandleLeft() instanceof BitmapDrawable) {
BitmapDrawable insetDrawable = (BitmapDrawable) edit.getTextSelectHandleLeft();
insetDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
edit.setTextSelectHandleLeft(insetDrawable);
Log.d("[UMI]", String.format("set caret handle left: %s", color));
if (Plugin.bridge.isDebug) {
Log.d("[UMI]", String.format("set caret handle left: %s", color));
}
}
} else {
try {
Expand Down Expand Up @@ -574,6 +597,49 @@ void setCaretColor(int color) {
}
}

/**
* Update locale list
*
* @param languageCode New language code
* @return Updated LocaleList
*/
private LocaleList UpdateLocaleList(String languageCode) {
LocaleList locales = edit.getImeHintLocales();
if (locales == null) {
return new LocaleList(new Locale(languageCode));
}
ArrayList<String> list = new ArrayList<>(Arrays.asList(locales.toLanguageTags().split(",")));
if (!list.contains(languageCode)) {
list.add(languageCode);
}
ArrayList<Locale> updated = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
updated.add(new Locale(list.get(i)));
}
return new LocaleList(updated.toArray(new Locale[updated.size()]));
}

/**
* Set keyboard language for input
*
* @param languageCode Language ISO code
*/
private void setKeyboardLanguage(String languageCode) {
if (Plugin.bridge.isDebug) {
Log.d("[UMI]", String.format("set keyboard language: %s", languageCode));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
edit.setImeHintLocales(UpdateLocaleList(languageCode));
} else {
Locale locale = new Locale(languageCode);
Configuration config = new Configuration();
config.locale = locale;
Plugin.activity.getResources().updateConfiguration(config, null);
}
InputMethodManager imm = (InputMethodManager) Plugin.activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.restartInput(edit);
}

/**
* Remove MobileInput
*/
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to this project will be documented in this file.

## [2.0.4] - 2024-09-10
- ### Added
- Change keyboard language

## [2.0.3] - 2024-08-28
- ### Added
- Custom text selection color (Android)
Expand Down
2 changes: 2 additions & 0 deletions Documentation~/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ This is the basic script for using UMI. Add this script to a game object with `T

`SetVisible(bool isVisible)` – switch field visibility

`SetLanguage(string value)` – change keyboard language

`SetRect(RectTransform inputRect)` – set new field size and position, this is useful if you want to move or resize the input field manually, at other times this is done automatically using the game object parameters

`SetContentType(InputContentType type)` – set content type to field
Expand Down
4 changes: 4 additions & 0 deletions Editor/MobileInputEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ public override void OnInspectorGUI() {
GUILayout.Label("Custom font name:", GUILayout.MaxWidth(LABEL_SIZE));
_target.CustomFont = GUILayout.TextField(_target.CustomFont);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("Keyboard language:", GUILayout.MaxWidth(LABEL_SIZE));
_target.KeyboardLanguage = GUILayout.TextField(_target.KeyboardLanguage);
GUILayout.EndHorizontal();
GUILayout.Space(SPACE);
_target.IsManualHideControl = GUILayout.Toggle(_target.IsManualHideControl, " Manual hide control");
GUILayout.Space(SPACE);
Expand Down
Binary file modified Plugins/Android/Mobileinput.aar
Binary file not shown.
85 changes: 82 additions & 3 deletions Plugins/iOS/MobileInput.mm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define SET_PTEXT_COLOR @"SET_PTEXT_COLOR"
#define SET_BG_COLOR @"SET_BG_COLOR"
#define SET_READ_ONLY @"SET_READ_ONLY"
#define SET_LANGUAGE @"SET_LANGUAGE"
#define SET_RECT @"SET_RECT"
#define ON_FOCUS @"ON_FOCUS"
#define ON_UNFOCUS @"ON_UNFOCUS"
Expand All @@ -31,6 +32,13 @@
/// Dict with inputs
NSMutableDictionary *mobileInputList = nil;

/// Custom textfield with overridden input mode
@interface CustomTextField : UITextField

/// Language code
@property (nonatomic, strong) NSString *languageCode;
@end

/// Interface for placeholder
@interface PlaceholderTextView : UITextView

Expand All @@ -42,6 +50,9 @@ @interface PlaceholderTextView : UITextView

/// Placeholder text color
@property(nonatomic, strong) UIColor *placeholderColor UI_APPEARANCE_SELECTOR;

/// Language code
@property (nonatomic, strong) NSString *languageCode;
@end

/// MobileInput interface
Expand Down Expand Up @@ -107,6 +118,35 @@ - (void)showKeyboard:(BOOL)value;
- (BOOL)isFocused;
@end

/// Custom textfield implemenation
@implementation CustomTextField

/// Set language for keyboard
/// - Parameter languageCode: ISO code
- (void)setLanguageCode:(NSString *)languageCode {
_languageCode = languageCode;
if ([self isFirstResponder]) {
[self resignFirstResponder];
[self becomeFirstResponder];
}
}

/// Overridden input
- (UITextInputMode *)textInputMode {
if (self.languageCode) {
for (UITextInputMode *keyboard in UITextInputMode.activeInputModes) {
if (keyboard.primaryLanguage) {
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:keyboard.primaryLanguage];
if ([locale.languageCode isEqualToString:self.languageCode]) {
return keyboard;
}
}
}
}
return [super textInputMode];
}

@end

/// Placeholder interface
@interface PlaceholderTextView ()
Expand Down Expand Up @@ -240,10 +280,35 @@ - (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

/// Set language for keyboard
/// - Parameter languageCode: ISO code
- (void)setLanguageCode:(NSString *)languageCode {
_languageCode = languageCode;
if ([self isFirstResponder]) {
[self resignFirstResponder];
[self becomeFirstResponder];
}
}

/// Overidden input
- (UITextInputMode *)textInputMode {
if (self.languageCode) {
for (UITextInputMode *keyboard in UITextInputMode.activeInputModes) {
if (keyboard.primaryLanguage) {
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:keyboard.primaryLanguage];
if ([locale.languageCode isEqualToString:self.languageCode]) {
return keyboard;
}
}
}
}
return [super textInputMode];
}

@end


/// MobileInput implimenation
/// MobileInput implemenation
@implementation MobileInput

/// Init MobileInput
Expand Down Expand Up @@ -434,6 +499,13 @@ - (void)processData:(NSDictionary *)data {
} else if ([msg isEqualToString:SET_VISIBLE]) {
BOOL isVisible = [[data valueForKey:@"is_visible"] boolValue];
[self setVisible:isVisible];
} else if ([msg isEqualToString:SET_LANGUAGE]) {
NSString *code = [data valueForKey:@"value"];
if (isMultiline) {
[(PlaceholderTextView *)editView setLanguageCode:code];
} else {
[(CustomTextField *)editView setLanguageCode:code];
}
}
}

Expand Down Expand Up @@ -512,7 +584,7 @@ - (void)create:(NSDictionary *)data {
float caretColor_r = [[data valueForKey:@"caret_color_r"] floatValue];
float caretColor_g = [[data valueForKey:@"caret_color_g"] floatValue];
float caretColor_b = [[data valueForKey:@"caret_color_b"] floatValue];
float caretColor_a = [[data valueForKey:@"caret_color_a"] floatValue];
float caretColor_a = [[data valueForKey:@"caret_color_a"] floatValue];
UIColor *caretColor = [UIColor colorWithRed:caretColor_r green:caretColor_g blue:caretColor_b alpha:caretColor_a];
NSString *contentType = [data valueForKey:@"content_type"];
NSString *alignment = [data valueForKey:@"align"];
Expand All @@ -525,6 +597,7 @@ - (void)create:(NSDictionary *)data {
BOOL password = NO;
NSString *inputType = [data valueForKey:@"input_type"];
NSString *keyboardType = [data valueForKey:@"keyboard_type"];
NSString *keyboardLanguage = [data valueForKey:@"keyboard_language"];
UIKeyboardType keyType = UIKeyboardTypeDefault;
if ([contentType isEqualToString:@"Autocorrected"]) {
autoCorrection = YES;
Expand Down Expand Up @@ -665,6 +738,9 @@ - (void)create:(NSDictionary *)data {
if (isChangeCaret) {
textView.tintColor = caretColor;
}
if (![keyboardLanguage isEqualToString:@"default"]) {
textView.languageCode = keyboardLanguage;
}
textView.delegate = self;
if (keyType == UIKeyboardTypeEmailAddress) {
textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
Expand All @@ -675,7 +751,7 @@ - (void)create:(NSDictionary *)data {
}
editView = textView;
} else {
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(x, y, width, height)];
CustomTextField *textField = [[CustomTextField alloc] initWithFrame:CGRectMake(x, y, width, height)];
textField.keyboardType = keyType;
[textField setFont:uiFont];
textField.delegate = self;
Expand All @@ -686,6 +762,9 @@ - (void)create:(NSDictionary *)data {
if (isChangeCaret) {
textField.tintColor = caretColor;
}
if (![keyboardLanguage isEqualToString:@"default"]) {
textField.languageCode = keyboardLanguage;
}
textField.returnKeyType = returnKeyType;
textField.autocorrectionType = autoCorrection ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo;
textField.contentVerticalAlignment = valign;
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ From UMI, you can edit these additional options:
- return button type
- return button callback
- custom font
- keyboard language on init
- manual hide option
- done & clear buttons option

Expand Down Expand Up @@ -139,6 +140,7 @@ With `OnKeyboardAction` you can control UI elements, such as moving the input fi
- `SetBackgroundColor` – change background color
- `SetContentType` – change input field content type
- `SetReadonly` – change readonly mode
- `SetLanguage` – change keyboard language

### How to use custom fonts

Expand Down
2 changes: 2 additions & 0 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ UMI также позволяет дополнительно настраива
- тип кнопки
- обработку кнопки
- свой шрифт
- язык клавиатуры при инициализации
- управление скрытием клавиатуры
- кнопки "Готово" и "Очистить"

Expand Down Expand Up @@ -138,6 +139,7 @@ public class Bootstrap : MonoBehaviour {
- `SetBackgroundColor` – изменение цвета фона
- `SetContentType` – изменение типа поля ввода
- `SetReadonly` – изменение состояния "только для чтения"
- `SetLanguage` – изменение языка клавиатуры

### Как использовать свои шрифты

Expand Down
2 changes: 1 addition & 1 deletion Runtime/MobileInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ public static float GetScreenScale() {
#else
return 1f;
#endif
}
}

/// <summary>
/// Update fonts
Expand Down
Loading

0 comments on commit bf78600

Please sign in to comment.