Skip to content

Commit 86b0e7f

Browse files
committed
Implement logic that uses TextView height to align text without lineHeight.
Reimplement solution from commit and comment (also relevant comment-1, commit-1, comment-2 and commit-2) which uses total height and number of lines to calculate average height. If textAttributes.mFontSize is not null, use the average lineHeight to position the text.
1 parent ee66a98 commit 86b0e7f

File tree

2 files changed

+39
-18
lines changed

2 files changed

+39
-18
lines changed

ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
3838
private final String mCurrentText;
3939
private String mTextAlignVertical;
4040
private int mHighestLineHeight;
41+
private int mLineHeight;
42+
private int mLineCount;
4143

4244
public CustomStyleSpan(
4345
int fontStyle,
@@ -67,7 +69,8 @@ public void updateDrawState(TextPaint ds) {
6769
mAssetManager,
6870
mTextAlignVertical,
6971
mCurrentText,
70-
mHighestLineHeight);
72+
mHighestLineHeight,
73+
mLineHeight);
7174
}
7275

7376
@Override
@@ -81,7 +84,8 @@ public void updateMeasureState(TextPaint paint) {
8184
mAssetManager,
8285
mTextAlignVertical,
8386
mCurrentText,
84-
mHighestLineHeight);
87+
mHighestLineHeight,
88+
mLineHeight);
8589
}
8690

8791
public int getStyle() {
@@ -105,7 +109,8 @@ private static void apply(
105109
AssetManager assetManager,
106110
@Nullable String textAlignVertical,
107111
String currentText,
108-
int highestLineHeight) {
112+
int highestLineHeight,
113+
int lineHeight) {
109114
Typeface typeface =
110115
ReactTypefaceUtils.applyStyles(paint.getTypeface(), style, weight, family, assetManager);
111116
paint.setFontFeatureSettings(fontFeatureSettings);
@@ -119,33 +124,39 @@ private static void apply(
119124
if (highestLineHeight != 0) {
120125
// the span with the highest lineHeight sets the height for all rows
121126
paint.baselineShift -= highestLineHeight / 2 - paint.getTextSize() / 2;
127+
} else if (lineHeight > 0) {
128+
paint.baselineShift -= lineHeight / 2 - paint.getTextSize() / 2;
122129
} else {
123130
// works only with single line and without fontSize
124131
// https://bit.ly/3W2eJKT
125132
// if lineHeight is not set, align the text using the font metrics
126133
// https://stackoverflow.com/a/27631737/7295772
127-
// top ------------- -26
128-
// ascent ------------- -30
129-
// baseline __my Text____ 0
130-
// descent _____________ 8
131-
// bottom _____________ 1
132-
paint.baselineShift += paint.getFontMetrics().top - paint.getFontMetrics().ascent;
134+
// top -------------
135+
// ascent -------------
136+
// baseline __my Text____
137+
// descent _____________
138+
// bottom _____________
139+
// paint.baselineShift += paint.getFontMetrics().top - paint.getFontMetrics().ascent;
133140
}
134141
}
135142
if (textAlignVertical == "bottom-child") {
136143
if (highestLineHeight != 0) {
137144
// the span with the highest lineHeight sets the height for all rows
138145
paint.baselineShift += highestLineHeight / 2 - paint.getTextSize() / 2;
146+
} else if (lineHeight > 0) {
147+
paint.baselineShift += lineHeight / 2 - paint.getTextSize() / 2;
139148
} else {
140149
// works only with single line and without fontSize
141150
// https://bit.ly/3W2eJKT
142-
paint.baselineShift += paint.getFontMetrics().bottom - paint.descent();
151+
// paint.baselineShift += paint.getFontMetrics().bottom - paint.descent();
143152
}
144153
}
145154
}
146155
}
147156

148-
public void updateSpan(int highestLineHeight) {
157+
public void updateSpan(int highestLineHeight, int lineCount, int lineHeight) {
149158
mHighestLineHeight = highestLineHeight;
159+
mLineCount = lineCount;
160+
mLineHeight = lineHeight;
150161
}
151162
}

ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
package com.facebook.react.views.text;
99

1010
import android.content.Context;
11+
import android.text.Layout;
1112
import android.text.Spannable;
1213
import androidx.annotation.NonNull;
1314
import androidx.annotation.Nullable;
15+
import com.facebook.common.logging.FLog;
1416
import com.facebook.react.R;
1517
import com.facebook.react.bridge.ReadableMap;
1618
import com.facebook.react.bridge.ReadableNativeMap;
@@ -43,6 +45,7 @@ public class ReactTextViewManager
4345
private static final short TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;
4446

4547
@VisibleForTesting public static final String REACT_CLASS = "RCTText";
48+
private static final String TAG = "ReactTextViewManager";
4649

4750
protected @Nullable ReactTextViewManagerCallback mReactTextViewManagerCallback;
4851

@@ -104,20 +107,27 @@ public void updateExtraData(ReactTextView view, Object extraData) {
104107

105108
CustomLineHeightSpan[] customLineHeightSpans =
106109
spannable.getSpans(0, spannable.length(), CustomLineHeightSpan.class);
110+
int highestLineHeight = 0;
107111
if (customLineHeightSpans.length > 0) {
108-
int highestLineHeight = 0;
109112
for (CustomLineHeightSpan span : customLineHeightSpans) {
110113
if (highestLineHeight == 0 || span.getLineHeight() > highestLineHeight) {
111114
highestLineHeight = span.getLineHeight();
112115
}
113116
}
117+
}
114118

115-
CustomStyleSpan[] customStyleSpans =
116-
spannable.getSpans(0, spannable.length(), CustomStyleSpan.class);
117-
if (customStyleSpans.length != 0) {
118-
for (CustomStyleSpan span : customStyleSpans) {
119-
span.updateSpan(highestLineHeight);
120-
}
119+
CustomStyleSpan[] customStyleSpans =
120+
spannable.getSpans(0, spannable.length(), CustomStyleSpan.class);
121+
if (customStyleSpans.length != 0) {
122+
Layout layout = view.getLayout();
123+
int lineCount = layout != null ? layout.getLineCount() : 1;
124+
int lineHeight = layout != null ? layout.getHeight() : 0;
125+
String methodName = new Object() {}.getClass().getEnclosingMethod().getName();
126+
FLog.w(
127+
"React::" + TAG,
128+
methodName + " update.getText(): " + (update.getText()) + " lineHeight: " + (lineHeight));
129+
for (CustomStyleSpan span : customStyleSpans) {
130+
span.updateSpan(highestLineHeight, lineCount, lineHeight);
121131
}
122132
}
123133
}

0 commit comments

Comments
 (0)