Skip to content

Commit 4472a07

Browse files
committed
Add numberOfLines parameter to limit number of lines
1 parent b7c722a commit 4472a07

File tree

6 files changed

+41
-10
lines changed

6 files changed

+41
-10
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ In both functions, the text to be measured is required, but the rest of the para
2828
- `textBreakStrategy` (Android)
2929
- `letterSpacing`
3030
- `allowFontScaling`
31+
- `numberOfLines`
3132
- `width`: Constraint for automatic line-break based on text-break strategy.
3233

3334
In addition, the library includes functions to obtain information about the fonts visible to the App.
@@ -100,6 +101,7 @@ allowFontScaling | boolean | true | To respect the user' setting of large
100101
letterSpacing | number | (none) | Additional spacing between characters (aka `tracking`).<br>**Note:** In iOS a zero cancels automatic kerning.<br>_All iOS, Android with API 21+_
101102
includeFontPadding | boolean | true | Include additional top and bottom padding, to avoid clipping certain characters.<br>_Android only_
102103
textBreakStrategy | string | 'highQuality' | One of 'simple', 'balanced', or 'highQuality'.<br>_Android only, with API 23+_
104+
numberOfLines | number | (none) | Limit the number of lines the text can render on
103105
width | number | MAX_INT | Restrict the width. The resulting height will vary depending on the automatic flow of the text.
104106
usePreciseWidth | boolean | false | If `true`, the result will include an exact `width` and the `lastLineWidth` property.<br>You can see the effect of this flag in the [sample App][sample-app].
105107
lineInfoForLine | number | (none) | If `>=0`, the result will include a [lineInfo](#lineinfo) property with information for the required line number.
@@ -228,6 +230,7 @@ allowFontScaling | boolean | true
228230
letterSpacing | number | (none)
229231
includeFontPadding | boolean | true
230232
textBreakStrategy | string | 'highQuality'
233+
numberOfLines | number | (none)
231234

232235
The result is a Promise that resolves to an array with the height of each block (in _SP_), in the same order in which the blocks were received.
233236

android/src/main/java/com/github/amarcruz/rntextsize/RNTextSizeConf.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ static boolean supportUpperCaseTransform() {
6969
final int fontStyle;
7070
final boolean includeFontPadding;
7171
final float letterSpacing;
72+
final @Nullable Integer numberOfLines;
7273

7374
/**
7475
* Proccess the user specs. Set both `allowFontScaling` & `includeFontPadding` to the user
@@ -88,6 +89,10 @@ static boolean supportUpperCaseTransform() {
8889

8990
// letterSpacing is supported in RN 0.55+
9091
letterSpacing = supportLetterSpacing() ? getFloatOrNaN("letterSpacing") : Float.NaN;
92+
93+
Integer rawNumberOfLines = getIntOrNull("numberOfLines");
94+
if (rawNumberOfLines != null && rawNumberOfLines < 0) rawNumberOfLines = null;
95+
numberOfLines = rawNumberOfLines;
9196
}
9297

9398
boolean has(@Nonnull final String name) {

android/src/main/java/com/github/amarcruz/rntextsize/RNTextSizeModule.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.text.SpannableStringBuilder;
1111
import android.text.StaticLayout;
1212
import android.text.TextPaint;
13+
import android.text.TextUtils;
1314

1415
import com.facebook.react.bridge.Arguments;
1516
import com.facebook.react.bridge.Promise;
@@ -118,13 +119,17 @@ public void measure(@Nullable final ReadableMap specs, final Promise promise) {
118119

119120
if (layout == null) {
120121
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
121-
layout = StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, hintWidth)
122+
StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, hintWidth)
122123
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
123124
.setBreakStrategy(conf.getTextBreakStrategy())
124125
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
125126
.setIncludePad(includeFontPadding)
126-
.setLineSpacing(SPACING_ADDITION, SPACING_MULTIPLIER)
127-
.build();
127+
.setLineSpacing(SPACING_ADDITION, SPACING_MULTIPLIER);
128+
if (conf.numberOfLines != null) {
129+
builder = builder.setMaxLines(conf.numberOfLines)
130+
.setEllipsize(TextUtils.TruncateAt.END);
131+
}
132+
layout = builder.build();
128133
} else {
129134
layout = new StaticLayout(
130135
text,
@@ -228,13 +233,17 @@ public void flatHeights(@Nullable final ReadableMap specs, final Promise promise
228233
sb.replace(0, sb.length(), text);
229234

230235
if (Build.VERSION.SDK_INT >= 23) {
231-
layout = StaticLayout.Builder.obtain(sb, 0, sb.length(), textPaint, (int) width)
236+
StaticLayout.Builder builder = StaticLayout.Builder.obtain(sb, 0, sb.length(), textPaint, (int) width)
232237
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
233238
.setBreakStrategy(textBreakStrategy)
234239
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
235240
.setIncludePad(includeFontPadding)
236-
.setLineSpacing(SPACING_ADDITION, SPACING_MULTIPLIER)
237-
.build();
241+
.setLineSpacing(SPACING_ADDITION, SPACING_MULTIPLIER);
242+
if (conf.numberOfLines != null) {
243+
builder = builder.setMaxLines(conf.numberOfLines)
244+
.setEllipsize(TextUtils.TruncateAt.END);
245+
}
246+
layout = builder.build();
238247
} else {
239248
layout = new StaticLayout(
240249
sb,

index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ declare module "react-native-text-size" {
7272
includeFontPadding?: boolean;
7373
/** @platform android (SDK 23+) */
7474
textBreakStrategy?: TSTextBreakStrategy;
75+
/** Number of lines to limit the text to */
76+
numberOfLines?: number;
7577
}
7678

7779
export type TSFontForStyle = {

index.js.flow

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ export type TSFontSpecs = {
7272
includeFontPadding?: boolean,
7373
/** @platform android (SDK 23+) */
7474
textBreakStrategy?: TSTextBreakStrategy,
75+
/** Number of lines to limit the text to */
76+
numberOfLines?: number,
7577
}
7678

7779
export type TSFontForStyle = {

ios/RNTextSize.m

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#import <React/RCTUtils.h>
77
#else
88
#import "React/RCTConvert.h" // Required when used as a Pod in a Swift project
9-
#import "React/RCTFont.h"
10-
#import "React/RCTUtils.h"
9+
#import <React/RCTFont.h>
10+
#import <React/RCTUtils.h>
1111
#endif
1212

1313
#import <CoreText/CoreText.h>
@@ -99,7 +99,12 @@ - (dispatch_queue_t)methodQueue {
9999

100100
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:maxSize];
101101
textContainer.lineFragmentPadding = 0.0;
102-
textContainer.lineBreakMode = NSLineBreakByClipping; // no maxlines support
102+
textContainer.lineBreakMode = NSLineBreakByClipping;
103+
104+
const NSInteger numberOfLines = [RCTConvert NSInteger:options[@"numberOfLines"]];
105+
if (numberOfLines > 0) {
106+
textContainer.maximumNumberOfLines = numberOfLines;
107+
}
103108

104109
NSLayoutManager *layoutManager = [NSLayoutManager new];
105110
[layoutManager addTextContainer:textContainer];
@@ -178,7 +183,12 @@ - (dispatch_queue_t)methodQueue {
178183

179184
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:maxSize];
180185
textContainer.lineFragmentPadding = 0.0;
181-
textContainer.lineBreakMode = NSLineBreakByClipping; // no maxlines support
186+
textContainer.lineBreakMode = NSLineBreakByClipping;
187+
188+
const NSInteger numberOfLines = [RCTConvert NSInteger:options[@"numberOfLines"]];
189+
if (numberOfLines > 0) {
190+
textContainer.maximumNumberOfLines = numberOfLines;
191+
}
182192

183193
NSLayoutManager *layoutManager = [NSLayoutManager new];
184194
[layoutManager addTextContainer:textContainer];

0 commit comments

Comments
 (0)