Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Android~/plugin/src/main/java/com/mopsicus/umi/MobileInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,21 @@ public static void processMessage(int id, final String data) {
JSONObject json = new JSONObject(data);
String msg = json.getString("msg");
if (msg.equals(CREATE)) {
if (mobileInputList.get(id) != null) {
return;
}
MobileInput input = new MobileInput(Plugin.layout);
input.Create(id, json);
mobileInputList.append(id, input);
input.Create(id, json);
} else {
MobileInput input = mobileInputList.get(id);
if (input != null) {
input.processData(json);
if (msg.equals(REMOVE)) {
input.Remove();
mobileInputList.remove(id);
} else {
input.processData(json);
}
}
}
} catch (JSONException e) {
Expand Down Expand Up @@ -306,6 +314,7 @@ private void Create(int id, JSONObject data) {
String alignment = data.getString("align");
String customFont = data.getString("font");
boolean multiline = data.getBoolean("multiline");
boolean isVisible = data.optBoolean("is_visible", true);
caretColor = Color.argb(caretColor_a, caretColor_r, caretColor_g, caretColor_b);
isCaretChange = data.getBoolean("caret_color");
edit = new EditText(Plugin.activity.getApplicationContext());
Expand Down Expand Up @@ -508,6 +517,8 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {
return false;
});

edit.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
edit.setEnabled(isVisible);
layout.addView(edit);
data = new JSONObject();
try {
Expand Down
6 changes: 5 additions & 1 deletion 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.6] - 2026-07-28
- ### Fixed
- Native input lifecycle and visibility races

## [2.0.5] - 2024-12-10
- ### Added
- Set caret position
Expand All @@ -26,4 +30,4 @@ All notable changes to this project will be documented in this file.
- Keyboard autohide on tap #110

## [2.0.0] - 2024-03-26
### Release v2
### Release v2
Binary file modified Plugins/Android/Mobileinput.aar
Binary file not shown.
19 changes: 16 additions & 3 deletions Plugins/iOS/MobileInput.mm
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,23 @@ + (void)processMessage:(int)inputId data:(NSString *)data {
NSDictionary *message = [Bridge jsonToDict:data];
NSString *msg = [message valueForKey:@"msg"];
if ([msg isEqualToString:CREATE]) {
NSNumber *key = [NSNumber numberWithInt:inputId];
if ([mobileInputList objectForKey:key]) {
return;
}
MobileInput *input = [[MobileInput alloc] initWith:mainViewController andTag:inputId];
[mobileInputList setObject:input forKey:key];
[input create:message];
[mobileInputList setObject:input forKey:[NSNumber numberWithInt:inputId]];
} else {
MobileInput *input = [mobileInputList objectForKey:[NSNumber numberWithInt:inputId]];
NSNumber *key = [NSNumber numberWithInt:inputId];
MobileInput *input = [mobileInputList objectForKey:key];
if (input) {
[input processData:message];
if ([msg isEqualToString:REMOVE]) {
[input remove];
[mobileInputList removeObjectForKey:key];
} else {
[input processData:message];
}
}
}
}
Expand Down Expand Up @@ -608,6 +618,8 @@ - (void)create:(NSDictionary *)data {
BOOL withClearButton = [[data valueForKey:@"with_clear_button"] boolValue];
isMultiline = [[data valueForKey:@"multiline"] boolValue];
BOOL isChangeCaret = [[data valueForKey:@"caret_color"] boolValue];
NSNumber *visibleValue = [data valueForKey:@"is_visible"];
BOOL isVisible = visibleValue ? [visibleValue boolValue] : YES;
BOOL autoCorrection = NO;
BOOL password = NO;
NSString *inputType = [data valueForKey:@"input_type"];
Expand Down Expand Up @@ -804,6 +816,7 @@ - (void)create:(NSDictionary *)data {
}
editView = textField;
}
editView.hidden = !isVisible;
[mainViewController.view addSubview:editView];
NSMutableDictionary *msg = [[NSMutableDictionary alloc] init];
[msg setValue:READY forKey:@"msg"];
Expand Down
73 changes: 68 additions & 5 deletions Runtime/MobileInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,21 @@ public abstract class MobileInputReceiver : MonoBehaviour {
/// <summary>
/// Current input id
/// </summary>
int _id = 0;
int _id = -1;

/// <summary>
/// Receiver registration state
/// </summary>
bool _isRegistered = false;

/// <summary>
/// Check whether native messages can safely use this receiver id
/// </summary>
protected bool IsRegistered {
get {
return _isRegistered;
}
}

/// <summary>
/// Init input and register interface
Expand All @@ -40,15 +54,19 @@ protected virtual void Start() {
#if !UNITY_EDITOR
_id = MobileInput.Register(this);
#endif
_isRegistered = true;
}

/// <summary>
/// Action on destroy
/// </summary>
protected virtual void OnDestroy() {
#if !UNITY_EDITOR
MobileInput.RemoveReceiver(_id);
if (_isRegistered) {
MobileInput.RemoveReceiver(_id);
}
#endif
_isRegistered = false;
}

/// <summary>
Expand All @@ -57,7 +75,9 @@ protected virtual void OnDestroy() {
/// <param name="data">Data</param>
protected void Execute(JsonObject data) {
#if !UNITY_EDITOR
MobileInput.Execute(_id, data);
if (_isRegistered) {
MobileInput.Execute(_id, data);
}
#endif
}

Expand Down Expand Up @@ -175,6 +195,30 @@ public class MobileInput : MonoBehaviour {
/// </summary>
static bool _isInited = false;

/// <summary>
/// Current application focus state
/// </summary>
static bool _applicationHasFocus = true;

/// <summary>
/// Current application pause state
/// </summary>
static bool _applicationPaused = false;

/// <summary>
/// Notify inputs when temporary application visibility changes
/// </summary>
internal static event Action OnApplicationVisibilityChange = delegate { };

/// <summary>
/// Whether native inputs may currently be displayed
/// </summary>
internal static bool CanShowInputs {
get {
return _applicationHasFocus && !_applicationPaused;
}
}

#if UNITY_IOS
/// <summary>
/// Send data to plugin input
Expand Down Expand Up @@ -360,7 +404,9 @@ public static int Register(MobileInputReceiver receiver) {
/// </summary>
/// <param name="id">Input id</param>
public static void RemoveReceiver(int id) {
_instance._inputs.Remove(id);
if ((object)_instance != null) {
_instance._inputs.Remove(id);
}
}

/// <summary>
Expand Down Expand Up @@ -406,6 +452,8 @@ public static void Init() {
Debug.Log($"[UMI] init");
#endif
_isInited = true;
_applicationHasFocus = Application.isFocused;
_applicationPaused = false;
var state = PlayerPrefs.GetInt(INIT_KEY, 0);
if (state == 0) {
UpdateFonts();
Expand Down Expand Up @@ -500,12 +548,27 @@ static void PrepareFontsAsset(string fileName) {
/// <summary>
/// Handler to check data on focus change
/// </summary>
void OnApplicationFocus(bool hasFocus) {
if (_applicationHasFocus == hasFocus) {
return;
}
_applicationHasFocus = hasFocus;
OnApplicationVisibilityChange();
}

/// <summary>
/// Handler to preserve callbacks and native visibility across app pause
/// </summary>
void OnApplicationPause(bool pauseStatus) {
if (_applicationPaused != pauseStatus) {
_applicationPaused = pauseStatus;
OnApplicationVisibilityChange();
}
if (!pauseStatus) {
if (_data != null) {
OnData(_data);
}
}
}
}
}
}
Loading