Skip to content

Commit

Permalink
Implement logic that uses TextView height to align text without lineH…
Browse files Browse the repository at this point in the history
…eight.

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.
  • Loading branch information
fabOnReact committed Jan 12, 2023
1 parent ee66a98 commit 86b0e7f
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
private final String mCurrentText;
private String mTextAlignVertical;
private int mHighestLineHeight;
private int mLineHeight;
private int mLineCount;

public CustomStyleSpan(
int fontStyle,
Expand Down Expand Up @@ -67,7 +69,8 @@ public void updateDrawState(TextPaint ds) {
mAssetManager,
mTextAlignVertical,
mCurrentText,
mHighestLineHeight);
mHighestLineHeight,
mLineHeight);
}

@Override
Expand All @@ -81,7 +84,8 @@ public void updateMeasureState(TextPaint paint) {
mAssetManager,
mTextAlignVertical,
mCurrentText,
mHighestLineHeight);
mHighestLineHeight,
mLineHeight);
}

public int getStyle() {
Expand All @@ -105,7 +109,8 @@ private static void apply(
AssetManager assetManager,
@Nullable String textAlignVertical,
String currentText,
int highestLineHeight) {
int highestLineHeight,
int lineHeight) {
Typeface typeface =
ReactTypefaceUtils.applyStyles(paint.getTypeface(), style, weight, family, assetManager);
paint.setFontFeatureSettings(fontFeatureSettings);
Expand All @@ -119,33 +124,39 @@ private static void apply(
if (highestLineHeight != 0) {
// the span with the highest lineHeight sets the height for all rows
paint.baselineShift -= highestLineHeight / 2 - paint.getTextSize() / 2;
} else if (lineHeight > 0) {
paint.baselineShift -= lineHeight / 2 - paint.getTextSize() / 2;
} else {
// works only with single line and without fontSize
// https://bit.ly/3W2eJKT
// if lineHeight is not set, align the text using the font metrics
// https://stackoverflow.com/a/27631737/7295772
// top ------------- -26
// ascent ------------- -30
// baseline __my Text____ 0
// descent _____________ 8
// bottom _____________ 1
paint.baselineShift += paint.getFontMetrics().top - paint.getFontMetrics().ascent;
// top -------------
// ascent -------------
// baseline __my Text____
// descent _____________
// bottom _____________
// paint.baselineShift += paint.getFontMetrics().top - paint.getFontMetrics().ascent;
}
}
if (textAlignVertical == "bottom-child") {
if (highestLineHeight != 0) {
// the span with the highest lineHeight sets the height for all rows
paint.baselineShift += highestLineHeight / 2 - paint.getTextSize() / 2;
} else if (lineHeight > 0) {
paint.baselineShift += lineHeight / 2 - paint.getTextSize() / 2;
} else {
// works only with single line and without fontSize
// https://bit.ly/3W2eJKT
paint.baselineShift += paint.getFontMetrics().bottom - paint.descent();
// paint.baselineShift += paint.getFontMetrics().bottom - paint.descent();
}
}
}
}

public void updateSpan(int highestLineHeight) {
public void updateSpan(int highestLineHeight, int lineCount, int lineHeight) {
mHighestLineHeight = highestLineHeight;
mLineCount = lineCount;
mLineHeight = lineHeight;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
package com.facebook.react.views.text;

import android.content.Context;
import android.text.Layout;
import android.text.Spannable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.react.R;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
Expand Down Expand Up @@ -43,6 +45,7 @@ public class ReactTextViewManager
private static final short TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3;

@VisibleForTesting public static final String REACT_CLASS = "RCTText";
private static final String TAG = "ReactTextViewManager";

protected @Nullable ReactTextViewManagerCallback mReactTextViewManagerCallback;

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

CustomLineHeightSpan[] customLineHeightSpans =
spannable.getSpans(0, spannable.length(), CustomLineHeightSpan.class);
int highestLineHeight = 0;
if (customLineHeightSpans.length > 0) {
int highestLineHeight = 0;
for (CustomLineHeightSpan span : customLineHeightSpans) {
if (highestLineHeight == 0 || span.getLineHeight() > highestLineHeight) {
highestLineHeight = span.getLineHeight();
}
}
}

CustomStyleSpan[] customStyleSpans =
spannable.getSpans(0, spannable.length(), CustomStyleSpan.class);
if (customStyleSpans.length != 0) {
for (CustomStyleSpan span : customStyleSpans) {
span.updateSpan(highestLineHeight);
}
CustomStyleSpan[] customStyleSpans =
spannable.getSpans(0, spannable.length(), CustomStyleSpan.class);
if (customStyleSpans.length != 0) {
Layout layout = view.getLayout();
int lineCount = layout != null ? layout.getLineCount() : 1;
int lineHeight = layout != null ? layout.getHeight() : 0;
String methodName = new Object() {}.getClass().getEnclosingMethod().getName();
FLog.w(
"React::" + TAG,
methodName + " update.getText(): " + (update.getText()) + " lineHeight: " + (lineHeight));
for (CustomStyleSpan span : customStyleSpans) {
span.updateSpan(highestLineHeight, lineCount, lineHeight);
}
}
}
Expand Down

0 comments on commit 86b0e7f

Please sign in to comment.