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

Add letter spacing for Android versions >= Lollipop (5.0). #13877

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion Libraries/Text/TextStylePropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const TextStylePropTypes = {
textShadowRadius: ReactPropTypes.number,
textShadowColor: ColorPropType,
/**
* @platform ios
* Specifies the letter spacing (kerning).
*/
letterSpacing: ReactPropTypes.number,
lineHeight: ReactPropTypes.number,
Expand Down
14 changes: 14 additions & 0 deletions RNTester/js/TextExample.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,20 @@ class TextExample extends React.Component {
right right right right right right right right right right right right right
</Text>
</RNTesterBlock>
<RNTesterBlock title="Letter Spacing">
<Text style={{letterSpacing: 0}}>
letterSpacing = 0
</Text>
<Text style={{letterSpacing: 2, marginTop: 5}}>
letterSpacing = 2
</Text>
<Text style={{letterSpacing: 9, marginTop: 5}}>
letterSpacing = 9
</Text>
<Text style={{letterSpacing: -1, marginTop: 5}}>
letterSpacing = -1
</Text>
</RNTesterBlock>
<RNTesterBlock title="Unicode">
<View>
<View style={{flexDirection: 'row'}}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public class ViewProps {
public static final String FONT_STYLE = "fontStyle";
public static final String FONT_FAMILY = "fontFamily";
public static final String LINE_HEIGHT = "lineHeight";
public static final String LETTER_SPACING = "letterSpacing";
public static final String NEEDS_OFFSCREEN_ALPHA_COMPOSITING = "needsOffscreenAlphaCompositing";
public static final String NUMBER_OF_LINES = "numberOfLines";
public static final String ELLIPSIZE_MODE = "ellipsizeMode";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ private static int parseNumericFontWeight(String fontWeightString) {
}

private float mLineHeight = Float.NaN;
private float mLetterSpacing = Float.NaN;
private boolean mIsColorSet = false;
private boolean mAllowFontScaling = true;
private int mColor;
Expand Down Expand Up @@ -389,6 +390,14 @@ public ReactTextShadowNode() {
}
}

public float getLetterSpacing() {
return mLetterSpacing;
}

public int getFontSize() {
return mFontSize;
}

// Returns a line height which takes into account the requested line height
// and the height of the inline images.
public float getEffectiveLineHeight() {
Expand Down Expand Up @@ -463,6 +472,12 @@ public void setAllowFontScaling(boolean allowFontScaling) {
}
}

@ReactProp(name = ViewProps.LETTER_SPACING, defaultFloat = UNSET)
public void setLetterSpacing(float letterSpacing) {
mLetterSpacing = letterSpacing == UNSET ? Float.NaN : letterSpacing;
markUpdated();
}

@ReactProp(name = ViewProps.TEXT_ALIGN)
public void setTextAlign(@Nullable String textAlign) {
if (textAlign == null || "auto".equals(textAlign)) {
Expand Down Expand Up @@ -652,6 +667,8 @@ public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
getPadding(Spacing.TOP),
getPadding(Spacing.END),
getPadding(Spacing.BOTTOM),
getLetterSpacing(),
getFontSize(),
getTextAlign(),
mTextBreakStrategy
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class ReactTextUpdate {
private final float mPaddingTop;
private final float mPaddingRight;
private final float mPaddingBottom;
private final float mLetterSpacing;
private final int mFontSize;
private final int mTextAlign;
private final int mTextBreakStrategy;

Expand All @@ -50,6 +52,8 @@ public ReactTextUpdate(
paddingTop,
paddingEnd,
paddingBottom,
0f,
12,
textAlign,
Layout.BREAK_STRATEGY_HIGH_QUALITY);
}
Expand All @@ -62,6 +66,8 @@ public ReactTextUpdate(
float paddingTop,
float paddingEnd,
float paddingBottom,
float letterSpacing,
int fontSize,
int textAlign,
int textBreakStrategy) {
mText = text;
Expand All @@ -71,6 +77,8 @@ public ReactTextUpdate(
mPaddingTop = paddingTop;
mPaddingRight = paddingEnd;
mPaddingBottom = paddingBottom;
mLetterSpacing = letterSpacing;
mFontSize = fontSize;
mTextAlign = textAlign;
mTextBreakStrategy = textBreakStrategy;
}
Expand Down Expand Up @@ -103,6 +111,14 @@ public float getPaddingBottom() {
return mPaddingBottom;
}

public float getLetterSpacing() {
return mLetterSpacing;
}

public int getFontSize() {
return mFontSize;
}

public int getTextAlign() {
return mTextAlign;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import android.view.ViewGroup;
import android.widget.TextView;

import com.facebook.react.uimanager.FloatUtil;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ReactCompoundView;
import com.facebook.react.uimanager.ViewDefaults;
import com.facebook.react.views.view.ReactViewBackgroundDrawable;
Expand All @@ -37,6 +39,7 @@ public class ReactTextView extends TextView implements ReactCompoundView {
private int mDefaultGravityVertical;
private boolean mTextIsSelectable;
private float mLineHeight = Float.NaN;
private float mLetterSpacing = Float.NaN;
private int mTextAlign = Gravity.NO_GRAVITY;
private int mNumberOfLines = ViewDefaults.NUMBER_OF_LINES;
private TextUtils.TruncateAt mEllipsizeLocation = TextUtils.TruncateAt.END;
Expand Down Expand Up @@ -65,6 +68,22 @@ public void setText(ReactTextUpdate update) {
(int) Math.floor(update.getPaddingRight()),
(int) Math.floor(update.getPaddingBottom()));

// API 21+: https://developer.android.com/reference/android/widget/TextView.html#setLetterSpacing(float)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
float nextLetterSpacing = update.getLetterSpacing();
int fontSize = update.getFontSize();
if (!FloatUtil.floatsEqual(mLetterSpacing, nextLetterSpacing)) {
mLetterSpacing = nextLetterSpacing;
if(Float.isNaN(mLetterSpacing)) {
setLetterSpacing((float) 0.0);
} else {
// Calculate EM from proper font pixels
// This does PX to EM conversions since Android does letterSpacing in EM
setLetterSpacing(1 + (mLetterSpacing - PixelUtil.toDIPFromPixel(fontSize)) / PixelUtil.toDIPFromPixel(fontSize));
}
}
}

int nextTextAlign = update.getTextAlign();
if (mTextAlign != nextTextAlign) {
mTextAlign = nextTextAlign;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public long measure(
mFontSize == UNSET ?
(int) Math.ceil(PixelUtil.toPixelFromSP(ViewDefaults.FONT_SIZE_SP)) : mFontSize);

// API 21+: https://developer.android.com/reference/android/widget/TextView.html#setLetterSpacing(float)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
editText.setLetterSpacing(getLetterSpacing());
}

if (mNumberOfLines != UNSET) {
editText.setLines(mNumberOfLines);
}
Expand Down Expand Up @@ -146,6 +151,8 @@ public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
getPadding(Spacing.TOP),
getPadding(Spacing.RIGHT),
getPadding(Spacing.BOTTOM),
getLetterSpacing(),
getFontSize(),
mTextAlign,
mTextBreakStrategy
);
Expand Down