Skip to content

Commit 0f23d85

Browse files
committed
feat: add lineHeight and lineSpacingExtra style props to TextWidget
1 parent 2b5b8b6 commit 0f23d85

4 files changed

Lines changed: 104 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add `lineHeight` and `lineSpacingExtra` style props to `TextWidget`
13+
1014
### Fixed
1115

1216
- Fix crash when deleting widgets if stored widget images cannot be listed

android/src/main/java/com/reactnativeandroidwidget/builder/widget/TextWidget.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import android.graphics.Typeface;
88
import android.os.Build;
99
import android.text.TextUtils;
10+
import android.util.TypedValue;
1011
import android.view.Gravity;
1112
import android.widget.TextView;
1213

@@ -50,20 +51,28 @@ public void applyProps() {
5051
}
5152
}
5253

54+
setFont();
55+
setShadow();
56+
5357
if (props.hasKey("letterSpacing")) {
5458
view.setLetterSpacing((float) (props.getDouble("letterSpacing") / getFontSize()));
5559
}
5660

61+
if (props.hasKey("lineSpacingExtra")) {
62+
view.setLineSpacing(dpToPx(props.getDouble("lineSpacingExtra")), 1.0f);
63+
}
64+
65+
if (props.hasKey("lineHeight")) {
66+
setLineHeight(props.getDouble("lineHeight"));
67+
}
68+
5769
if (props.hasKey("truncate")) {
5870
view.setEllipsize(TextUtils.TruncateAt.valueOf(props.getString("truncate")));
5971
}
6072

6173
if (props.hasKey("maxLines")) {
6274
view.setMaxLines(props.getInt("maxLines"));
6375
}
64-
65-
setFont();
66-
setShadow();
6776
}
6877

6978
private void setFont() {
@@ -115,6 +124,15 @@ private void setShadow() {
115124
}
116125
}
117126

127+
private void setLineHeight(double lineHeight) {
128+
int lineHeightPx = textSizeToPx(lineHeight);
129+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
130+
view.setLineHeight(lineHeightPx);
131+
} else {
132+
TextViewCompat.setLineHeight(view, lineHeightPx);
133+
}
134+
}
135+
118136
private float getFontSize() {
119137
float fontSize = 12;
120138
if (props.hasKey("fontSize")) {
@@ -129,4 +147,8 @@ private int getFontSizeUnit() {
129147
}
130148
return COMPLEX_UNIT_SP;
131149
}
150+
151+
private int textSizeToPx(double value) {
152+
return Math.round(TypedValue.applyDimension(getFontSizeUnit(), (float) value, appContext.getResources().getDisplayMetrics()));
153+
}
132154
}

example/src/screens/TextScreen.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ const FONT_WEIGHT: (
3434
'900',
3535
];
3636

37+
const LOREM_IPSUM =
38+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer porta risus at sem facilisis, vitae luctus augue volutpat.';
39+
3740
function TextWidgetDemo({
3841
fontStyle,
3942
fontWeight,
@@ -67,6 +70,38 @@ function TextWidgetDemo({
6770
);
6871
}
6972

73+
function LineHeightDemo() {
74+
return (
75+
<FlexWidget>
76+
<TextWidget
77+
text={LOREM_IPSUM}
78+
style={{
79+
width: 320,
80+
fontSize: 15,
81+
lineHeight: 24,
82+
color: '#111827',
83+
}}
84+
/>
85+
</FlexWidget>
86+
);
87+
}
88+
89+
function LineSpacingExtraDemo() {
90+
return (
91+
<FlexWidget>
92+
<TextWidget
93+
text={LOREM_IPSUM}
94+
style={{
95+
width: 320,
96+
fontSize: 15,
97+
lineSpacingExtra: 6,
98+
color: '#111827',
99+
}}
100+
/>
101+
</FlexWidget>
102+
);
103+
}
104+
70105
export function TextScreen() {
71106
return (
72107
<ScrollView
@@ -100,6 +135,20 @@ export function TextScreen() {
100135
</View>
101136
))
102137
)}
138+
139+
<Text style={styles.sectionTitle}>lineHeight</Text>
140+
<WidgetPreview
141+
renderWidget={() => <LineHeightDemo />}
142+
height={120}
143+
width={320}
144+
/>
145+
146+
<Text style={styles.sectionTitle}>lineSpacingExtra</Text>
147+
<WidgetPreview
148+
renderWidget={() => <LineSpacingExtraDemo />}
149+
height={120}
150+
width={320}
151+
/>
103152
</ScrollView>
104153
);
105154
}
@@ -118,4 +167,12 @@ const styles = StyleSheet.create({
118167
height: 30,
119168
marginBottom: 16,
120169
},
170+
sectionTitle: {
171+
width: 320,
172+
marginTop: 8,
173+
marginBottom: 8,
174+
fontSize: 18,
175+
fontWeight: '600',
176+
color: 'black',
177+
},
121178
});

src/widgets/TextWidget.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ interface TextWidgetInternalProps extends CommonInternalProps {
3131
adjustsFontSizeToFit?: boolean;
3232
textAlign?: 'center' | 'left' | 'right';
3333
letterSpacing?: number;
34+
lineHeight?: number;
35+
lineSpacingExtra?: number;
3436
color?: HexColor;
3537
shadow?: {
3638
radius: number;
@@ -67,6 +69,8 @@ export interface TextWidgetStyle extends CommonStyleProps {
6769
adjustsFontSizeToFit?: boolean;
6870
textAlign?: 'center' | 'left' | 'right';
6971
letterSpacing?: number;
72+
lineHeight?: number;
73+
lineSpacingExtra?: number;
7074

7175
textShadowColor?: ColorProp;
7276
textShadowRadius?: number;
@@ -112,9 +116,9 @@ TextWidget.convertProps = (props: TextWidgetProps): TextWidgetInternalProps => {
112116
...(props.style?.fontStyle ? { fontStyle: props.style.fontStyle } : {}),
113117
...(props.style?.fontWeight ? { fontWeight: props.style.fontWeight } : {}),
114118
...(props.style?.textAlign ? { textAlign: props.style.textAlign } : {}),
115-
...(props.style?.letterSpacing
116-
? { letterSpacing: props.style.letterSpacing }
117-
: {}),
119+
...copyNumberStyleProp(props.style ?? {}, 'letterSpacing'),
120+
...copyNumberStyleProp(props.style ?? {}, 'lineHeight'),
121+
...copyNumberStyleProp(props.style ?? {}, 'lineSpacingExtra'),
118122
...(props.style?.adjustsFontSizeToFit
119123
? { adjustsFontSizeToFit: props.style.adjustsFontSizeToFit }
120124
: {}),
@@ -126,6 +130,17 @@ TextWidget.convertProps = (props: TextWidgetProps): TextWidgetInternalProps => {
126130
};
127131
TextWidget.__name__ = 'TextWidget';
128132

133+
function copyNumberStyleProp(
134+
style: TextWidgetStyle,
135+
propName: 'lineHeight' | 'lineSpacingExtra' | 'letterSpacing'
136+
): Partial<TextWidgetInternalProps> {
137+
if (style[propName] !== undefined) {
138+
return { [propName]: style[propName] };
139+
}
140+
141+
return {};
142+
}
143+
129144
function buildTextShadow(
130145
style: TextWidgetStyle
131146
): Partial<TextWidgetInternalProps> {

0 commit comments

Comments
 (0)