Skip to content

Commit 5819538

Browse files
fabOnReactfacebook-github-bot
authored andcommitted
Fix selectionColor doesn't style Android TextInput selection handles (#31007)
Summary: This issue fixes #30283 selectionColor does not change the handles color. The method setCursorColor changes the cursor color of field `mCursorDrawable` using a reflection for Android Devices lower then API 28. This fix adds a reflection to change color of the left, center and right handles of a selection (mTextSelectHandleLeftRes, mTextSelectHandleRes and mTextSelectHandleRightRes). ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [Android] [Fixed] - Fix selectionColor doesn't style Android TextInput selection handles Pull Request resolved: #31007 Test Plan: This changes fix the Java API for which I can not write Java tests as explained in commit 709a441 The java TextInputTest was excluded from the test suite in commit 709a441 as they need the Yoga libraries to run **<details><summary>CLICK TO OPEN TESTS RESULTS - API 22</summary>** <p> left/right handles do not change color with the cursor | **BEFORE** | |:-------------------------:| | <img src="https://user-images.githubusercontent.com/24992535/108241887-98351180-714c-11eb-9c7b-7c693ea0bb06.png" width="250" height="" /> | center Handle color does not change color | **BEFORE** | |:-------------------------:| | <img src="https://user-images.githubusercontent.com/24992535/108241904-9ec38900-714c-11eb-9fc3-dbd26f83b979.png" width="250" height="" /> | The left and right handle change color with the cursor color | **AFTER** | |:-------------------------:| | <img src="https://user-images.githubusercontent.com/24992535/108241796-805d8d80-714c-11eb-9d90-6871ddaea86f.png" width="250" height="" /> | The center handle color is correctly updated | **AFTER** | |:-------------------------:| | <img src="https://user-images.githubusercontent.com/24992535/108241571-45f3f080-714c-11eb-8475-86e6dea64d73.png" width="250" height="" /> | `setCursorColor` changes correctly the cursor color | **AFTER** | |:-------------------------:| | <img src="https://user-images.githubusercontent.com/24992535/108241484-2d83d600-714c-11eb-8a0c-80a847f28537.png" width="250" height="" /> | Default Colors do not have issues | **AFTER** | |:-------------------------:| | <img src="https://user-images.githubusercontent.com/24992535/108241346-04634580-714c-11eb-933e-0dce504498a8.png" width="250" height="" /> | | **AFTER** | |:-------------------------:| | <img src="https://user-images.githubusercontent.com/24992535/108241347-04fbdc00-714c-11eb-902a-fc057cf94986.png" width="250" height="" /> | </p> </details> Reviewed By: ShikaSD Differential Revision: D28682935 Pulled By: sota000 fbshipit-source-id: ff037c93f36bbf20c915373b995bbfd8e8ca92d0
1 parent c29ec46 commit 5819538

File tree

1 file changed

+42
-27
lines changed

1 file changed

+42
-27
lines changed

ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java

+42-27
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
158158
private static final String KEYBOARD_TYPE_URI = "url";
159159
private static final InputFilter[] EMPTY_FILTERS = new InputFilter[0];
160160
private static final int UNSET = -1;
161+
private static final String[] DRAWABLE_FIELDS = {
162+
"mCursorDrawable", "mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"
163+
};
164+
private static final String[] DRAWABLE_RESOURCES = {
165+
"mCursorDrawableRes",
166+
"mTextSelectHandleLeftRes",
167+
"mTextSelectHandleRightRes",
168+
"mTextSelectHandleRes"
169+
};
161170

162171
protected @Nullable ReactTextViewManagerCallback mReactTextViewManagerCallback;
163172

@@ -507,34 +516,40 @@ public void setCursorColor(ReactEditText view, @Nullable Integer color) {
507516
}
508517

509518
// The evil code that follows uses reflection to achieve this on Android 8.1 and below.
510-
// Based on
511-
// http://stackoverflow.com/questions/25996032/how-to-change-programatically-edittext-cursor-color-in-android.
512-
try {
513-
// Get the original cursor drawable resource.
514-
Field cursorDrawableResField = TextView.class.getDeclaredField("mCursorDrawableRes");
515-
cursorDrawableResField.setAccessible(true);
516-
int drawableResId = cursorDrawableResField.getInt(view);
517-
518-
// The view has no cursor drawable.
519-
if (drawableResId == 0) {
520-
return;
521-
}
519+
// Based on https://tinyurl.com/3vff8lyu https://tinyurl.com/vehggzs9
520+
for (int i = 0; i < DRAWABLE_RESOURCES.length; i++) {
521+
try {
522+
Field drawableResourceField = TextView.class.getDeclaredField(DRAWABLE_RESOURCES[i]);
523+
drawableResourceField.setAccessible(true);
524+
int resourceId = drawableResourceField.getInt(view);
522525

523-
Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId);
524-
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
525-
Drawable[] drawables = {drawable, drawable};
526-
527-
// Update the current cursor drawable with the new one.
528-
Field editorField = TextView.class.getDeclaredField("mEditor");
529-
editorField.setAccessible(true);
530-
Object editor = editorField.get(view);
531-
Field cursorDrawableField = editor.getClass().getDeclaredField("mCursorDrawable");
532-
cursorDrawableField.setAccessible(true);
533-
cursorDrawableField.set(editor, drawables);
534-
} catch (NoSuchFieldException ex) {
535-
// Ignore errors to avoid crashing if these private fields don't exist on modified
536-
// or future android versions.
537-
} catch (IllegalAccessException ex) {
526+
// The view has no cursor drawable.
527+
if (resourceId == 0) {
528+
return;
529+
}
530+
531+
Drawable drawable = ContextCompat.getDrawable(view.getContext(), resourceId);
532+
533+
Drawable drawableCopy = drawable.mutate();
534+
drawableCopy.setColorFilter(color, PorterDuff.Mode.SRC_IN);
535+
536+
Field editorField = TextView.class.getDeclaredField("mEditor");
537+
editorField.setAccessible(true);
538+
Object editor = editorField.get(view);
539+
540+
Field cursorDrawableField = editor.getClass().getDeclaredField(DRAWABLE_FIELDS[i]);
541+
cursorDrawableField.setAccessible(true);
542+
if (DRAWABLE_RESOURCES[i] == "mCursorDrawableRes") {
543+
Drawable[] drawables = {drawableCopy, drawableCopy};
544+
cursorDrawableField.set(editor, drawables);
545+
} else {
546+
cursorDrawableField.set(editor, drawableCopy);
547+
}
548+
} catch (NoSuchFieldException ex) {
549+
// Ignore errors to avoid crashing if these private fields don't exist on modified
550+
// or future android versions.
551+
} catch (IllegalAccessException ex) {
552+
}
538553
}
539554
}
540555

0 commit comments

Comments
 (0)