Skip to content

Commit

Permalink
feat: custom caret/cursor/handles color
Browse files Browse the repository at this point in the history
  • Loading branch information
mopsicus committed Aug 27, 2024
1 parent ff34957 commit 25b58ba
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 1 deletion.
98 changes: 98 additions & 0 deletions Android~/plugin/src/main/java/com/mopsicus/umi/MobileInput.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package com.mopsicus.umi;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
Expand All @@ -18,10 +24,13 @@
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Field;

public class MobileInput {

private static final String CREATE = "CREATE_EDIT";
Expand Down Expand Up @@ -68,6 +77,16 @@ public class MobileInput {
*/
private int editInputType = 0;

/**
* Cached caret color
*/
private int caretColor = Color.GRAY;

/**
* Cached flag to change caret to custom color or not
*/
private boolean isCaretChange = false;

/**
* List of inputs
*/
Expand Down Expand Up @@ -255,13 +274,19 @@ private void Create(int id, JSONObject data) {
int placeHolderColor_g = (int) (255.0f * data.getDouble("placeholder_color_g"));
int placeHolderColor_b = (int) (255.0f * data.getDouble("placeholder_color_b"));
int placeHolderColor_a = (int) (255.0f * data.getDouble("placeholder_color_a"));
int caretColor_r = (int) (255.0f * data.getDouble("caret_color_r"));
int caretColor_g = (int) (255.0f * data.getDouble("caret_color_g"));
int caretColor_b = (int) (255.0f * data.getDouble("caret_color_b"));
int caretColor_a = (int) (255.0f * data.getDouble("caret_color_a"));
String contentType = data.getString("content_type");
String inputType = data.optString("input_type");
String keyboardType = data.optString("keyboard_type");
String returnKeyType = data.getString("return_key_type");
String alignment = data.getString("align");
String customFont = data.getString("font");
boolean multiline = data.getBoolean("multiline");
caretColor = Color.argb(caretColor_a, caretColor_r, caretColor_g, caretColor_b);
isCaretChange = data.getBoolean("caret_color");
edit = new EditText(Plugin.activity.getApplicationContext());
edit.setSingleLine(!multiline);
edit.setId(this.id);
Expand Down Expand Up @@ -476,6 +501,74 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}

/***
* Set cursor/caret/handles color
*
* @param color Color value
*/
void setCaretColor(int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (edit.getTextCursorDrawable() instanceof InsetDrawable) {
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 (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 (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 (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));
}
} else {
try {
Resources res = edit.getContext().getResources();
Field field = TextView.class.getDeclaredField("mEditor");
field.setAccessible(true);
Object editor = field.get(edit);
field = TextView.class.getDeclaredField("mCursorDrawableRes");
field.setAccessible(true);
int cursorDrawableRes = field.getInt(edit);
Drawable cursorDrawable = res.getDrawable(cursorDrawableRes).mutate();
cursorDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
Drawable[] drawables = {cursorDrawable, cursorDrawable};
field = editor.getClass().getDeclaredField("mCursorDrawable");
field.setAccessible(true);
field.set(editor, drawables);
String[] resFieldNames = {"mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes"};
String[] drawableFieldNames = {"mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"};
for (int i = 0; i < resFieldNames.length; i++) {
String resFieldName = resFieldNames[i];
String drawableFieldName = drawableFieldNames[i];
field = TextView.class.getDeclaredField(resFieldName);
field.setAccessible(true);
int selectHandleRes = field.getInt(edit);
Drawable selectHandleDrawable = res.getDrawable(selectHandleRes).mutate();
selectHandleDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
field = editor.getClass().getDeclaredField(drawableFieldName);
field.setAccessible(true);
field.set(editor, selectHandleDrawable);
}
} catch (Exception e) {
if (Plugin.bridge.isDebug) {
Log.e("[UMI]", String.format("set caret error: %s", e));
}
}
}
}

/**
* Remove MobileInput
*/
Expand Down Expand Up @@ -534,6 +627,11 @@ private void SetFocus(boolean isFocus) {
}
if (isFocus) {
edit.requestFocus();
if (isCaretChange) {
setCaretColor(caretColor);
} else {
setCaretColor(Color.GRAY);
}
} else {
edit.clearFocus();
}
Expand Down
2 changes: 1 addition & 1 deletion Plugins/Android/MobileInput.aar.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified Plugins/Android/Mobileinput.aar
Binary file not shown.
12 changes: 12 additions & 0 deletions Plugins/iOS/MobileInput.mm
Original file line number Diff line number Diff line change
Expand Up @@ -509,12 +509,18 @@ - (void)create:(NSDictionary *)data {
float placeHolderColor_b = [[data valueForKey:@"placeholder_color_b"] floatValue];
float placeHolderColor_a = [[data valueForKey:@"placeholder_color_a"] floatValue];
UIColor *placeHolderColor = [UIColor colorWithRed:placeHolderColor_r green:placeHolderColor_g blue:placeHolderColor_b alpha:placeHolderColor_a];
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];
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"];
NSString *customFont = [data valueForKey:@"font"];
BOOL withDoneButton = [[data valueForKey:@"with_done_button"] boolValue];
BOOL withClearButton = [[data valueForKey:@"with_clear_button"] boolValue];
isMultiline = [[data valueForKey:@"multiline"] boolValue];
BOOL isChangeCaret = [[data valueForKey:@"caret_color"] boolValue];
BOOL autoCorrection = NO;
BOOL password = NO;
NSString *inputType = [data valueForKey:@"input_type"];
Expand Down Expand Up @@ -656,6 +662,9 @@ - (void)create:(NSDictionary *)data {
textView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
textView.placeholder = placeholder;
textView.placeholderColor = placeHolderColor;
if (isChangeCaret) {
textView.tintColor = caretColor;
}
textView.delegate = self;
if (keyType == UIKeyboardTypeEmailAddress) {
textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
Expand All @@ -674,6 +683,9 @@ - (void)create:(NSDictionary *)data {
textField.text = @"";
textField.textColor = textColor;
textField.backgroundColor = backgroundColor;
if (isChangeCaret) {
textField.tintColor = caretColor;
}
textField.returnKeyType = returnKeyType;
textField.autocorrectionType = autoCorrection ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo;
textField.contentVerticalAlignment = valign;
Expand Down
11 changes: 11 additions & 0 deletions Runtime/MobileInputField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct MobileInputConfig {
public bool Multiline;
public Color TextColor;
public Color BackgroundColor;
public bool ChangeCaret;
public Color CaretColor;
public string ContentType;
public string InputType;
public string KeyboardType;
Expand Down Expand Up @@ -306,6 +308,7 @@ protected override void OnDestroy() {
base.OnDestroy();
}

#if UNITY_ANDROID
/// <summary>
/// Handler for app focus lost
/// </summary>
Expand All @@ -325,6 +328,7 @@ void OnApplicationPause(bool hasPause) {
}
SetVisible(!hasPause);
}
#endif

/// <summary>
/// Current InputField for external access
Expand Down Expand Up @@ -420,6 +424,8 @@ void PrepareNativeEdit() {
var placeHolder = _inputObject.placeholder.GetComponent<TextMeshProUGUI>();
_config.Placeholder = placeHolder.text;
_config.PlaceholderColor = placeHolder.color;
_config.CaretColor = _inputObject.caretColor;
_config.ChangeCaret = _inputObject.customCaretColor;
_config.CharacterLimit = _inputObject.characterLimit;
var rect = GetScreenRectFromRectTransform(_inputObjectText.rectTransform);
var ratio = rect.height / _inputObjectText.rectTransform.rect.height;
Expand Down Expand Up @@ -573,6 +579,11 @@ void CreateNativeEdit() {
data["placeholder_color_g"] = InvariantCultureString(_config.PlaceholderColor.g);
data["placeholder_color_b"] = InvariantCultureString(_config.PlaceholderColor.b);
data["placeholder_color_a"] = InvariantCultureString(_config.PlaceholderColor.a);
data["caret_color_r"] = InvariantCultureString(_config.CaretColor.r);
data["caret_color_g"] = InvariantCultureString(_config.CaretColor.g);
data["caret_color_b"] = InvariantCultureString(_config.CaretColor.b);
data["caret_color_a"] = InvariantCultureString(_config.CaretColor.a);
data["caret_color"] = _config.ChangeCaret;
data["multiline"] = _config.Multiline;
data["input_type"] = _config.InputType;
data["keyboard_type"] = _config.KeyboardType;
Expand Down

0 comments on commit 25b58ba

Please sign in to comment.