Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Measure text accurately before laying it out and get font information from your App.

License

NotificationsYou must be signed in to change notification settings

aMarCruz/react-native-text-size

Repository files navigation

npm VersionLicense

Measure text accurately before laying it out and get font information from your App (Android and iOS).

In my country (México), software developers are poorly paid, so I have had to look for another job to earn a living and I cannot dedicate more time to maintaining this and other repositories that over the years have never generated any money for me. If anyone is interested in maintaining this repository, I'd be happy to transfer it to them, along with the associated npm package.
En mi país (México), los desarrolladores de software somos pésimamente pagados, por lo que he tenido que buscar otro trabajo para ganarme la vida y no puedo dedicar más tiempo a mantener éste y otros repositorios que a través de los años nunca me generaron dinero. Si a alguien le interesa dar mantenimiento a este repositorio, con gusto se lo transferiré, así como el paquete de npm asociado.

There are two main functions:flatHeights to obtain the height of different blocks of text simultaneously, optimized for components such as<FlatList> or<RecyclerListView>.

The other one ismeasure, which gets detailed information about one block of text:

  • The width used by the text, with an option to calculate the real width of the largest line.
  • The height of the text, with or without paddings.
  • The number of lines.
  • The width of the last line.
  • Extended information of a given line.

The width and height are practically the same as those received from theonLayout 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:

  • fontFamily
  • fontSize
  • fontWeight
  • fontStyle
  • fontVariant (iOS)
  • includeFontPadding (Android)
  • textBreakStrategy (Android)
  • letterSpacing
  • allowFontScaling
  • width: Constraint for automatic line-break based on text-break strategy.

In addition, 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 ⭐️ orko-fi.

Installation

Mostly automatic installation from npm

yarn add react-native-text-sizereact-native link react-native-text-size

Change thecompile directive toimplementation in the dependencies block of the android/app/build.gradle file.

Requirements:

  • React Native v0.57 or later.
  • Android API 16 or iOS 9.0 and above.

For versions prior to 0.56 of React Native, please usereact-native-text-size v2.1.1

SeeManual Installation on the Wiki as an alternative if you have problems with automatic installation.

API

measure

measure(options:TSMeasureParams):Promise<TSMeasureResult>

This function measures the text as RN does and its result is consistent* with that ofText'sonLayout event. It takes a subset of the properties used by<Text> to describe the font and other options to use.

If you providewidth, the measurement will apply automatic wrapping in addition to the explicit line breaks.

*There may be some inconsistencies in iOS, see thisKnow 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 useflatHeights, which is optimized for batch processing.

TSMeasureParams

Plain JS object with this properties (onlytext is required):

PropertyTypeDefaultNotes
textstring(none)This is the only required parameter and may includeemojis or be empty, but itmust not benull.
If this is an empty string the resultingwidth will be zero.
fontFamilystringOS dependentThe 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.
fontWeightstring'normal'On android, numeric ranges has no granularity and '500' to '900' becomes 'bold', but you can use afontFamily of specific weight ("sans-serif-thin", "sans-serif-medium", etc).
fontSizenumber14The default font size comes from RN.
fontStylestring'normal'One of "normal" or "italic".
fontVariantarray(none)iOS only
allowFontScalingbooleantrueTo respect the user' setting of large fonts (i.e. use SP units).
letterSpacingnumber(none)Additional spacing between characters (akatracking).
Note: In iOS a zero cancels automatic kerning.
All iOS, Android with API 21+
includeFontPaddingbooleantrueInclude additional top and bottom padding, to avoid clipping certain characters.
Android only
textBreakStrategystring'highQuality'One of 'simple', 'balanced', or 'highQuality'.
Android only, with API 23+
widthnumberMAX_INTRestrict the width. The resulting height will vary depending on the automatic flow of the text.
usePreciseWidthbooleanfalseIftrue, the result will include an exactwidth and thelastLineWidth property.
You can see the effect of this flag in thesample App.
lineInfoForLinenumber(none)If>=0, the result will include alineInfo property with information for the required line number.

Thesample App shows interactively the effect of these parameters on the screen.

TSMeasureResult

measure returns a Promise that resolves to a JS object with this properties:

PropertyTypeNotes
widthnumberTotal used width. It may be less or equal to thewidth option.
On Android, this value may vary depending on theusePreciseWidth flag.
heightnumberTotal height, including top and bottom padding ifincludingFontPadding was set (the default).
lastLineWidthnumberWidth of the last line, without trailing blanks.
IfusePreciseWidth isfalse (the default), this property is undefined.
lineCountnumberNumber of lines, taking into account hard and automatic line breaks.
lineInfoobjectLine information.
If thelineInfoForLine option is not given, this property is undefined.

lineInfo

If the value of thelineInfoForLine is greater or equal thanlineCount, this info is for the last line (i.e.lineCount - 1).

PropertyTypeNotes
linenumberLine number of this info, base 0.
It can be less than the requested line number iflineInfoForLine is out of range.
startnumberText offset of the beginning of this line.
endnumberText offset after the lastvisible character (so whitespace is not counted) on this line.
bottomnumberThe vertical position of the bottom of this line, including padding.
widthnumberHorizontal extent of this line, including leading margin indent, but excluding trailing whitespace.
UseusePreciseWidth:true to get an accurate value for this property.

In case of error, the promise is rejected with an extended Error object with one of the following error codes, as a literal string:

CodeDetails
E_MISSING_PARAMETERSmeasure requires an object with the parameters, which was not provided.
E_MISSING_TEXTThe text to measure isnull or was not provided.
E_INVALID_FONT_SPECThe font specification is not valid. It is unlikely that this will happen on Android.
E_UNKNOWN_ERRORWell... who knows?

Example

//...importrnTextSize,{TSFontSpecs}from'react-native-text-size'typeProps={}typeState={width:number,height:number}// On iOS 9+ will show 'San Francisco' and 'Roboto' on AndroidconstfontSpecs:TSFontSpecs={  fontFamily=undefined,  fontSize=24,  fontStyle='italic',  fontWeight='bold',}consttext='I ❤️ rnTextSize'classTestextendsComponent<Props,State>{  state={width:0,height:0,}asynccomponentDidMount(){constwidth=Dimensions.get('window').width*0.8constsize=awaitrnTextSize.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 reversiblerender(){const{width,height}=this.statereturn(<Viewstyle={{padding:12}}><Textstyle={{ width, height, ...fontSpecs}}>{text}</Text></View>)}}

flatHeights

flatHeights(options:TSHeightsParams):Promise<number[]>

Calculate the height of each of the strings in an array.

This is an alternative tomeasure designed for cases in which you have to calculate the height of numerous text blocks with common characteristics (width, font, etc), a typical use case with<FlatList> or<RecyclerListView> components.

The measurement uses the same algorithm asmeasure 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):

 measureflatHeights
Android49,6241,091
iOS1,949732

In the future I will prepare an example of its use with FlatList and multiple styles on the same card.

TSHeightsParams

This is an object similar to the one you pass tomeasure, but thetext option is an array of strings and theusePreciseWidth andlineInfoForLine options are ignored.

PropertyTypeDefault
textstring[](none)
widthnumberInfinity
fontFamilystringOS dependent
fontWeightstring'normal'
fontSizenumber14
fontStylestring'normal'
fontVariantarray(none)
allowFontScalingbooleantrue
letterSpacingnumber(none)
includeFontPaddingbooleantrue
textBreakStrategystring'highQuality'

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

Unlike measure,null elements returns 0 without generating error, and empty strings returns the same height that RN assigns to empty<Text> components (the difference of the result betweennull and empty is intentional).

Example

//...importrnTextSize,{TSFontSpecs}from'react-native-text-size'typeProps={texts:string[]}typeState={heights:number[]}// On iOS 9+ will show 'San Francisco' and 'Roboto' on AndroidconstfontSpecs:TSFontSpecs={  fontFamily=undefined,  fontSize=24,  fontStyle='italic',  fontWeight='bold',}consttexts=['I ❤️ rnTextSize','I ❤️ rnTextSize using flatHeights','Thx for flatHeights']classTestextendsComponent<Props,State>{  state={heights:[],}asynccomponentDidMount(){const{ texts}=this.propsconstwidth=Dimensions.get('window').width*0.8constheights=awaitrnTextSize.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.propsconst{heights}=this.statereturn(<Viewstyle={{padding:12}}>{texts.map((text,index)=>(<Textstyle={{height:heights[index], ...fontSpecs}}>{text}</Text>))}</View>)}}

specsForTextStyles

specsForTextStyles():Promise<{[key:string]:TSFontForStyle}>

Get system font information for the running OS.

This is a wrapper for the iOSUIFont.preferredFontForTextStyle method and the current AndroidMaterial Design Type Scale styles.

The result is a Promise that resolves to a JS object whose keys depend on the OS, but its values are in turn objects fully compatible with those used in the RN styles, so it can be used to stylize<Text> or<TextInput> components:

TSFontForStyle

PropertyTypeNotes
fontFamilystringSystem family name or font face.
fontSizenumberFont size inSP (unscaled).
fontStyleTSFontStyleOnly if 'italic', undefined if the style is 'normal'.
fontWeightTSFontWeightOnly if 'bold', undefined if the weight is 'normal'.
fontVariantTSFontVariant[] or nulliOS only. Currently, no style includes this property.
letterSpacingnumberOmitted if running on Android with RN lower than 0.55

To know the key names, please seeKeys from specsForTextStyles in the Wiki.

I have not tried to normalize the keys of the result because, with the exception of two or three, they have a different interpretation in each OS, but you can use them to create custom styles according to your needs.

fontFromSpecs

fontFromSpecs(specs:TSFontSpecs):Promise<TSFontInfo>

Returns the characteristics of the font obtained from the given specifications.

TSFontSpecs

This parameter is a subset ofTSMeasureParams, so the details are omitted here.

PropertyTypeDefault
fontFamilystringiOS: 'San Francisco', Android: 'Roboto'
fontWeightstring'normal'
fontSizenumber14
fontStylestring'normal'
fontVariantstring[](none)
letterSpacingnumber0

fontFromSpecs uses an implicitallowsFontScaling:true and, since this is not a measuring function,includeFontPadding has no meaning.

TSFontInfo

The result is a Promise that resolves to a JS object with info for the given font and size, units inSP in Android or points in iOS, using floating point numbers where applicable*.

PropertyTypeDetails
fontFamilystringIn Android it is the same string passed as parameter.
fontNamestringiOS only, alwaysundefined in Android.
fontSizenumberIt may be different from the given parameter if the parameter includes decimals.
fontStylestring'normal' or 'italic'.
fontWeightstring'normal' or 'bold', on iOS it can go from '100' to '900'.
fontVariantstring[]iOS only, alwaysundefined in Android.
ascendernumberThe recommended distance above the baseline for singled spaced text.
descendernumberThe recommended distance below the baseline for singled spaced text.
capHeightnumberiOS only Height of capital characters.
xHeightnumberiOS only Height of lowercase "x".
topnumberAndroid only. Maximum distance above the baseline for the tallest glyph in the font.
bottomnumberAndroid only. Maximum distance below the baseline for the lowest glyph in the font.
leadingnumberThe recommended additional space to add between lines of text.
lineHeightnumberThe recommended line height. It should be greater if text contain Unicode symbols, such as emojis.
_hashnumberHash code, may be useful for debugging.

*Using floats is more accurate than integers and allows you to use your preferred rounding method, but consider 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

fontFamilyNames():Promise<string[]>

Returns a Promise for an array of font family names available on the system.

On iOS, this uses theUIFont.familyNames method of the UIKit.

On Android, the result is hard-coded for the system fonts and complemented dynamically with the fonts installed by your app, if any.

SeeAbout Android Fonts andCustom Fonts in the Wiki to know more about this list.

fontNamesForFamilyName

fontNamesForFamilyName(fontFamily: string):Promise<string[]>

Wrapper for theUIFont.fontNamesForFamilyName method of UIKit, returns an array of font names available in a particular font family.

You can use the rnTextSize'sfontFamilyNames function to get an array of the available font family names on the system.

This is aniOS only function, on Android it always resolves tonull.

Known Issues

Inconsistent width between platforms

In iOS, the resulting width of both,measure andflatHeights, includes leading whitespace while in Android these are discarded.

Incorrent height (iOS)

On iOS, RN takes into account 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).

letterSpacing not scaling (iOS)

RN does not support theDynamic Type Sizes, but does an excellent job imitating this feature throughallowFontScaling ...except forletterSpacing that is not scaled.

I hope that a future version of RN solves this issue.

lineHeight Support

Although rnTextSize provides the resultinglineHeight in some functions, it does not support it as a parameter because RN uses a non-standard algorithm to set it. I recommend you do not uselineHeight unless it is strictly necessary, but if you use it, try to make it 30% or more than the font size, or use rnTextSizefontFromSpecs method if you want more precision.

Nested Text

Nested<Text> components (or with images inside) can be rasterized with dimensions different from those calculated, rnTextSize does not accept multiple sizes.

TODO

  • Normalized tracking or letter spacing in font info.
  • More testing, including Android and iOS TVs.
  • Learn the beautiful English, to make better docs.
  • Find something nice in the ugly Objective-C.

Support my Work

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!

License

TheBSD 2-Clause "Simplified" License.

© 2018-2019, Alberto Martínez. All rights reserved.


[8]ページ先頭

©2009-2025 Movatter.jp