Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix selectionColor doesn't style Android TextInput selection handles #31007

Closed
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
private static final String KEYBOARD_TYPE_VISIBLE_PASSWORD = "visible-password";
private static final InputFilter[] EMPTY_FILTERS = new InputFilter[0];
private static final int UNSET = -1;
private static final String[] DRAWABLE_FIELDS = {
"mCursorDrawable", "mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"
fabOnReact marked this conversation as resolved.
Show resolved Hide resolved
};
private static final String[] DRAWABLE_RESOURCES = {
"mCursorDrawableRes",
"mTextSelectHandleLeftRes",
"mTextSelectHandleRightRes",
"mTextSelectHandleRes"
};

protected @Nullable ReactTextViewManagerCallback mReactTextViewManagerCallback;

Expand Down Expand Up @@ -446,34 +455,40 @@ public void setCursorColor(ReactEditText view, @Nullable Integer color) {
}

// The evil code that follows uses reflection to achieve this on Android 8.1 and below.
// Based on
// http://stackoverflow.com/questions/25996032/how-to-change-programatically-edittext-cursor-color-in-android.
try {
// Get the original cursor drawable resource.
Field cursorDrawableResField = TextView.class.getDeclaredField("mCursorDrawableRes");
cursorDrawableResField.setAccessible(true);
int drawableResId = cursorDrawableResField.getInt(view);

// The view has no cursor drawable.
if (drawableResId == 0) {
return;
}
// Based on https://tinyurl.com/3vff8lyu https://tinyurl.com/vehggzs9
for (int i = 0; i < DRAWABLE_RESOURCES.length; i++) {
try {
Field drawableResourceField = TextView.class.getDeclaredField(DRAWABLE_RESOURCES[i]);
drawableResourceField.setAccessible(true);
int resourceId = drawableResourceField.getInt(view);

Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
Drawable[] drawables = {drawable, drawable};

// Update the current cursor drawable with the new one.
Field editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
Object editor = editorField.get(view);
Field cursorDrawableField = editor.getClass().getDeclaredField("mCursorDrawable");
cursorDrawableField.setAccessible(true);
cursorDrawableField.set(editor, drawables);
} catch (NoSuchFieldException ex) {
// Ignore errors to avoid crashing if these private fields don't exist on modified
// or future android versions.
} catch (IllegalAccessException ex) {
// The view has no cursor drawable.
if (resourceId == 0) {
return;
}

Drawable drawable = ContextCompat.getDrawable(view.getContext(), resourceId);

Drawable drawableCopy = drawable.mutate();
drawableCopy.setColorFilter(color, PorterDuff.Mode.SRC_IN);

Field editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
Object editor = editorField.get(view);

Field cursorDrawableField = editor.getClass().getDeclaredField(DRAWABLE_FIELDS[i]);
cursorDrawableField.setAccessible(true);
if (DRAWABLE_RESOURCES[i] == "mCursorDrawableRes") {
Drawable[] drawables = {drawableCopy, drawableCopy};
cursorDrawableField.set(editor, drawables);
} else {
cursorDrawableField.set(editor, drawableCopy);
}
} catch (NoSuchFieldException ex) {
// Ignore errors to avoid crashing if these private fields don't exist on modified
// or future android versions.
} catch (IllegalAccessException ex) {
}
}
}

Expand Down