Skip to content

Commit

Permalink
Allow overriding EditText construction in ReactTextInputShadowNode (#…
Browse files Browse the repository at this point in the history
…27782)

Summary:
This PR makes it possible for subclasses of `ReactTextInputShadowNode` to control the construction of the "dummy" `EditText` instance that `ReactTextInputShadowNode` internally uses to determine the expected height of the view. This PR does not change the default behavior, it just opens up that default to being overriden.

This is useful in the case of custom views that have different behavior from a "default" `EditText` instance (`new EditText(context)`). For example, it might have a different style applied.

As a side benefit, this change also makes it easy to have subclasses not apply the default theme, which can allow the custom view to avoid a longstanding crash issue (#17530).

## Changelog

[Android] [Added] - Allow overriding `EditText` construction in `ReactTextInputShadowNode`
Pull Request resolved: #27782

Test Plan: All tests pass.

Reviewed By: mdvacca

Differential Revision: D19450593

Pulled By: JoshuaGross

fbshipit-source-id: 8d2ce6117246fc3e2108623312b38583af5722b3
  • Loading branch information
mchowning authored and facebook-github-bot committed Jan 21, 2020
1 parent a27e31c commit a5b5d1a
Showing 1 changed file with 14 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class ReactTextInputShadowNode extends ReactBaseTextShadowNode
implements YogaMeasureFunction {

private int mMostRecentEventCount = UNSET;
private @Nullable EditText mDummyEditText;
private @Nullable EditText mInternalEditText;
private @Nullable ReactTextInputLocalData mLocalData;

@VisibleForTesting public static final String PROP_TEXT = "text";
Expand Down Expand Up @@ -75,20 +75,20 @@ public void setThemedContext(ThemedReactContext themedContext) {
// of Android), and it cannot be changed.
// So, we have to enforce it as a default padding.
// TODO #7120264: Cache this stuff better.
EditText editText = new EditText(getThemedContext());
EditText editText = createInternalEditText();
setDefaultPadding(Spacing.START, ViewCompat.getPaddingStart(editText));
setDefaultPadding(Spacing.TOP, editText.getPaddingTop());
setDefaultPadding(Spacing.END, ViewCompat.getPaddingEnd(editText));
setDefaultPadding(Spacing.BOTTOM, editText.getPaddingBottom());

mDummyEditText = editText;
mInternalEditText = editText;

// We must measure the EditText without paddings, so we have to reset them.
mDummyEditText.setPadding(0, 0, 0, 0);
mInternalEditText.setPadding(0, 0, 0, 0);

// This is needed to fix an android bug since 4.4.3 which will throw an NPE in measure,
// setting the layoutParams fixes it: https://code.google.com/p/android/issues/detail?id=75877
mDummyEditText.setLayoutParams(
mInternalEditText.setLayoutParams(
new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
Expand All @@ -101,7 +101,7 @@ public long measure(
float height,
YogaMeasureMode heightMode) {
// measure() should never be called before setThemedContext()
EditText editText = Assertions.assertNotNull(mDummyEditText);
EditText editText = Assertions.assertNotNull(mInternalEditText);

if (mLocalData != null) {
mLocalData.apply(editText);
Expand Down Expand Up @@ -249,4 +249,12 @@ public void setPadding(int spacingType, float padding) {
super.setPadding(spacingType, padding);
markUpdated();
}

/**
* May be overriden by subclasses that would like to provide their own instance of the internal
* {@code EditText} this class uses to determine the expected size of the view.
*/
protected EditText createInternalEditText() {
return new EditText(getThemedContext());
}
}

0 comments on commit a5b5d1a

Please sign in to comment.