Measure Text Accurely Before Laying It Out and Get Font Information from your app (Android and iOS).
| In my country (Mexico), Software Developers are poorly paid, so i have had to look for another job to earn a living and I Cannot dedicated more time to mainting Thising This and Other repositories that over the years have needed generated any money for me. If anyone is intersted in Maintaining This Repository, I'd Be Happy to Transfer It To Them, Along With The Associated NPM Package. |
|---|
| In my country (Mexico), software developers are terrified, so I had to look for another job to make a living and I cannot spend more time keeping this and other repositories than for years never generated money. If someone is interested in maintaining this repository, I will gladly transfer it, as well as the associated NPM package. |
There are two main function: flatHeights to obtain the height of different blocks of text simultaneously, optimized for components such as <FlatList> or <RecyclerListView> .
The other one is measure , which gets detailed information about the text of text:
The Width and Height Are Practical The Same As Those Received From The onLayout Event of A <Text> component with the Same Properties.
In Both Functions, The Text to Be Measured Is Required, But the Rest of the Parameters Are Optional and Work in the Same Way As with React Native:
fontFamilyfontSizefontWeightfontStylefontVariant (iOS)includeFontPadding (Android)textBreakStrategy (Android)letterSpacingallowFontScalingwidth : Constraint for Automatic Line-Break Based on Text-Broak Strategy.In Adionion, The Library Includes Functions to Obtain Information about the fonts visible to the app.
If it has helped you, please support my work with a Star ️ or ko-fi.
Mostly Automatic Installation from NPM
yarn add react-native-text-size
react-native link react-native-text-size CHANGE The compile Directive to implementation in the Dependencies Block of the Android/App/Build.grale File.
Requirements:
For Versions Prior to 0.56 of React Native, please use react-native-text-size v2.1.1
See manual installation on the wiki as an alternative if you have problems with automatic installation.
measure
flatHeights
specsForTextStyles
fontFromSpecs
fontFamilyNames
fontNamesForFamilyName
measure ( options : TSMeasureParams ) : Promise < TSMeasureResult > This Function Measures The Text as rn does and its results is consisting* with that of Text 's onlayout event. It takes a subset of the properties used by <Text> to describe the font and oher options to use.
If you Provide width , The Measurement Will Apply Automatic Wraping in Addition to the Explicit Line Breaks.
* There may be inconsistenties in ios, see This know issue to know more.
Note:
Although This Function is Accurate and Provides Complete Information, it can be heavy if the text is a Lot, Like The One That Can Be Displayed In A Flatlist. For these cases, it is Better to use flatHeights , which is optimized for Batch Processing.
Plain JS Object with This Properties (only text is required):
| PROPERTY | Type | Default | Notes |
|---|---|---|---|
| Text | String | (None) | This is the only required parameter and may include emojis or be empty, but it must not be null .If this is an empty string the resulting width will be zero. |
| Fontfamily | String | I depend | The Default is The Same Applied by React Native: Roboto in Android, San Francisco In iOS. Note: Device Manufacturer or Custom Rom Can Change The Default Font. |
| Fontweight | String | 'normal' | On Android, Number Ranges you have not granularity and '500' to '900' Becomes 'bold', but you can use fontFamily of Specific Weight ("Sans-Serif-Thin", "Sans-Serif-Medium", etc). |
| Fontsize | Number | 14 | The Default Font Size Comes from RN. |
| Fontstyle | String | 'normal' | One of "Normal" or "Italic". |
| Fontvariant | Array | (None) | ios Only |
| AllowfontScaling | Boolean | True | To respect the User 'Setting of Large Fonts (IE USE SP Units). |
| Letterspacing | Number | (None) | Additional Spacing Between Characters (Aka tracking ).Note: In ios a zero cancels Automatic Kerning. All iOS, Android with Api 21+ |
| Includefontpadding | Boolean | True | Addionional Top and Bottom Padding, to Avoid Clipping Certain Characters. Android Only |
| Textbreakstrategy | String | 'highqualy' | One of 'Simple', 'Balanced', or 'highqualy'. Android Only, with API 23+ |
| Width | Number | Max_int | Restrict the width. The Result Height Will Vary depending on the Automatic Flow of the Text. |
| Useprecisewidth | Boolean | false | If true , The result Will include an exact width and the lastLineWidth property.You Can See The Effect of This Flag in the Sample App. |
| Lineinfoforline | Number | (None) | If >=0 , The result Will include Lineinfo Property with Information for the Required Line Number. |
The Sample App Shows Interactively The Effect of these parameters on the screen.
measure Returns A promise that resolves to a js object with This properties:
| PROPERTY | Type | Notes |
|---|---|---|
| Width | Number | Total used width. It may be les or equal to the width option.On Android, This Value May Vary depending on the usePreciseWidth Flag. |
| Height | Number | Total Height, Including Top and Bottom Padding if includingFontPadding was set (The Default). |
| Lastlinewidth | Number | Width of the Last Line, Without Trailing Blanks. IF usePreciseWidth IS false (The Default), This Property is Undefined. |
| Linecount | Number | Number of Lines, Taking into Account Hard and Automatic Line Breaks. |
| Lineinfo | Object | LINE INFORMATION. If the lineInfoForLine option is not Given, This Property is Undefined. |
If the Value of the lineInfoForLine is greelter or equal lineCount , This info is for the last line (Ie lineCount - 1).
| PROPERTY | Type | Notes |
|---|---|---|
| LINE | Number | LINE NUMBER OF THIS INFO, Base 0. It can be less than the lineInfoForLine line. |
| Start | Number | Text offset of the Beginning of this Line. |
| end | Number | Text offset After the last visible Character (So Whitespace is not counted) on this line. |
| Bottom | Number | The Vertical Position of the Bottom of this Line, Including Padding. |
| Width | Number | Horizontal Exte of This Line, Including Leading Margin Indent, But Excluding Trailing Whitespace. Use usePreciseWidth:true to Get an Accurate Value for This Property. |
In case of error, The Promise is rejected with an extended Object with one of the following error codes, as a literal string:
| Code | Details |
|---|---|
| E_MISSING_Parameters | measure requires an object with the parameters, which was not provided. |
| E_MISSING_TEXT | The Text to Measure is null Or was not provided. |
| E_invalid_font_spec | The Font Specification is not valid. It is unlikely that This Will Happen on Android. |
| E_UNKNOWN_ERROR | Well ... Who knows? |
//...
import rnTextSize , { TSFontSpecs } from 'react-native-text-size'
type Props = { }
type State = { width : number , height : number }
// On iOS 9+ will show 'San Francisco' and 'Roboto' on Android
const fontSpecs : TSFontSpecs = {
fontFamily = undefined ,
fontSize = 24 ,
fontStyle = 'italic' ,
fontWeight = 'bold' ,
}
const text = 'I ❤️ rnTextSize'
class Test extends Component < Props , State > {
state = {
width : 0 ,
height : 0 ,
}
async componentDidMount ( ) {
const width = Dimensions . get ( 'window' ) . width * 0.8
const size = await rnTextSize . measure ( {
text , // text to measure, can include symbols
width , // max-width of the "virtual" container
... fontSpecs , // RN font specification
} )
this . setState ( {
width : size . width ,
height : size . height
} )
}
// The result is reversible
render ( ) {
const { width , height } = this . state
return (
< View style = { { padding : 12 } } >
< Text style = { { width , height , ... fontSpecs } } >
{ text }
</ Text >
</ View >
)
}
} flatHeights ( options : TSHeightsParams ) : Promise < number [ ] >Calculate The Height of Each of the Strings in An Array.
This is an alternative to measure designated for cases in which you have calculate the height of numberous text blocks with common characteristics (width, font, etc.), Typical use case with <FlatList> or <RecyclerListView> Components.
The Measurement Uses The Same Algorithm As measure But It Returns Only The Height of Each Block and, by Avoiding Multiple Steps Through The Bridge, It is Faster ... Much Faster on Android!
I DID Tests on 5,000 Random Text Blocks and these were the results (MS):
measure | flatHeights | |
|---|---|---|
| Android | 49,624 | 1,091 |
| iOS | 1,949 | 732 |
In the Future I Will prepare an Example of ITS USE WITH FLATLIST AND MULTIPLE Styles On The Same Card.
This is an object similar to the one you pass to measure , but the text option is an array of strings and the usePreciseWidth and lineInfoForLine options are ignored.
| PROPERTY | Type | Default |
|---|---|---|
| Text | String [] | (None) |
| Width | Number | Infinity |
| Fontfamily | String | I depend |
| Fontweight | String | 'normal' |
| Fontsize | Number | 14 |
| Fontstyle | String | 'normal' |
| Fontvariant | Array | (None) |
| AllowfontScaling | Boolean | True |
| Letterspacing | Number | (None) |
| Includefontpadding | Boolean | True |
| Textbreakstrategy | String | 'highqualy' |
The results 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.
Unlike Measure, null Elements Returns 0 Without Genering Error, and Empty Strings Returns The Same Height That Rn Assigns to null <Text> components.
//...
import rnTextSize , { TSFontSpecs } from 'react-native-text-size'
type Props = { texts : string [ ] }
type State = { heights : number [ ] }
// On iOS 9+ will show 'San Francisco' and 'Roboto' on Android
const fontSpecs : TSFontSpecs = {
fontFamily = undefined ,
fontSize = 24 ,
fontStyle = 'italic' ,
fontWeight = 'bold' ,
}
const texts = [ 'I ❤️ rnTextSize' , 'I ❤️ rnTextSize using flatHeights' , 'Thx for flatHeights' ]
class Test extends Component < Props , State > {
state = {
heights : [ ] ,
}
async componentDidMount ( ) {
const { texts } = this . props
const width = Dimensions . get ( 'window' ) . width * 0.8
const heights = await rnTextSize . flatHeights ( {
text : texts , // array of texts to measure, can include symbols
width , // max-width of the "virtual" container
... fontSpecs , // RN font specification
} )
this . setState ( {
heights
} )
}
render ( ) {
const { texts } = this . props
const { heights } = this . state
return (
< View style = { { padding : 12 } } >
{ texts . map (
( text , index ) => (
< Text style = { { height : heights [ index ] , ... fontSpecs } } >
{ text }
</ Text >
)
) }
</ View >
)
}
} specsForTextStyles ( ) : Promise < { [ key : string ] : TSFontForStyle } >Get System Font Information for The Running Os.
This is a wrapper for the UIFont.preferredFontForTextStyle oros
The result is a promise that resolves to a js object Whoe Keys depend on the os, but it Values are in turn Objects Fully Compatible withHese used in the rn Styles, so it can be used to stylize <Text> or <TextInput> components:
| PROPERTY | Type | Notes |
|---|---|---|
| Fontfamily | String | System Family Name or Font Face. |
| Fontsize | Number | FONT SIZE IN SP (UNSCALED). |
| Fontstyle | Tsfontstyle | Only if 'Italic', Undefined if the style is 'normal'. |
| Fontweight | Tsfontweight | Only if 'bold', Undefined if the Weight is 'normal'. |
| Fontvariant | Tsfontvariant [] or null | ios Only . Currently, no style includes This property. |
| Letterspacing | Number | Omitted if running on Android with rn loower than 0.55 |
To know the key names, please See Keys from Specsfortextstyles in the wiki.
I have not tried to normalize The Keys of the Result Becouse, with the Exception of Two Or Three, They have a different interpretation in each os, but you can use them to create customs styles according to your needs.
fontFromSpecs ( specs : TSFontSpecs ) : Promise < TSFontInfo >Returns the Characteristics of the Font Obtained from the Given Specifications.
This parameter is a subset of TSMeasureParams , so the details are omitted here.
| PROPERTY | Type | Default |
|---|---|---|
| Fontfamily | String | iOS: 'San Francisco', Android: 'Roboto' |
| Fontweight | String | 'normal' |
| Fontsize | Number | 14 |
| Fontstyle | String | 'normal' |
| Fontvariant | String [] | (None) |
| Letterspacing | Number | 0 |
fontFromSpecs uses an implicit allowsFontScaling:true and, since this is not a measuring function, includeFontPadding you have not meaning.
The results is a promise that resolves to a js object with info for the Given Font and Size, units in sp in Android or Points in iOS, using floating point numbers WHERE APPLIBLE*.
| PROPERTY | Type | Details |
|---|---|---|
| Fontfamily | String | In Android it is the Same String passed as parameter. |
| Fontname | String | iOS Only , Always undefined in Android. |
| Fontsize | Number | It may be different from the Given parameter if the parameter includes decimals. |
| Fontstyle | String | 'Normal' or 'Italic'. |
| Fontweight | String | 'Normal' or 'bold', on ios can go from '100' to '900'. |
| Fontvariant | String [] | iOS Only , Always undefined in Android. |
| ascend | Number | The Recommended Distance ABOVE The Baseline for Singled Spaced Text. |
| descend | Number | The recommended distance below the baseline for singled Spaced text. |
| Capheight | Number | iOS Only Height of Capital Characters. |
| Xheight | Number | ios Only Height of Lowercase "X". |
| top | Number | Android Only . MAXIMUM DISTANCE ABOVE THE BASELINE FOR THE TALLLES GLYPH IN THE FONT. |
| Bottom | Number | Android Only . MAXIMUM DISTANCE BELOW THE BASELINE FOR THE LOWEST GLYPH IN THE FONT. |
| Leading | Number | The recommended Additionional Space to Add Between Lines of Text. |
| Lineheight | Number | The recommended line height. It Should Be Greater If Text Contain Unicode Symbols, Such As Emojis. |
| _Hash | Number | Hash Code, May Be Useful for Debugging. |
* Using floats is More Accurate Than Integers and Allows You To Use Your Prefer Rounding Method, But No More than 5 Digits of Precision in This Values. Also, Remember Rn Doesn't Work With Subpixels in Android and Will Truncate This Values.
See more in:
Understanding Typography at the Google Material Design Site.
About Text Handling in iOS for iOS.
fontFamilyNames ( ) : Promise < string [ ] >Returns a promise for an array of font family names Available on the system.
On iOS, This you use the UIFont.familyNames Method of the Uikit.
On Android, The Result is Hard-Coded for the System Fonts and Complement Dynamically With The Fonts Installed By Your App, If Any.
See about Android Fonts and Custom Fonts in the Wiki To Know More About This List.
fontNamesForFamilyName ( fontFamily : string ) : Promise < string [ ] > Wrapper for the UIFont.fontNamesForFamilyName Method of Uikit, Returns An Array of Font Names Available in A particular Font Family.
You can use the Rntextsize's fontFamilyNames Function to Get An Array of the Available Font Family Names On The System.
This is an ios Only Function, on Android it always resolves to null .
In iOS, The Resulting Width of Both, measure and flatHeights , Includes Leading Whitespace While in Android these are Discarded.
On ios, rn takes into accounts the absolute position on the screen to calculate the dimensions. RNTEXTSize Can't Do That and Both, Width and Height, Can Have a Difference of Up to 1 Pixel (Not Point).
RN DOES NOT SUPPORT THE DYNAMIC TYPE SIZES, BUT DOES AN EXCELLENT JOB IMITATING THIS FEATURE THRUCH allowFontScaling ... EXCEP FOR letterSpacing THAT IS NOT SCALED.
I Hope That A Future Version of Rn Solves This Issue.
Although Rntextsize Provides The Resulting lineHeight in Sum Functions, It Does Not Support It As a Parameter BeCouse RN you use non-standard algorithm to set it. I recommend you do not use lineHeight unless it is strictly needy, but if you use it, try to make it 30% or more than the font size, or use rntextsize fontFromSpecs method if you want more precision.
Nested <Text> components (or with images inside)
I'M A Full-Stack Developer with More than 20 Year of Experience and I try to Share Most of My Work for Free and Help Others, But This Takes A Significant Amount of Time and Effort So, If You Like My Work, please consider ...
Of Course, Feedback, PRS, and Stars Are Also Welcome?
Thanks for Your Support!
The BSD 2-Clause "Simplified" License.
© 2018-2019, Alberto Martínez. All Rights Reserved.