Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native - how to set fixed width to individual characters (number, letter, etc)

Tags:

I am having a problem in a React Native app I'm building. I have a stopwatch and since each number character has a different width, when the time is increased the text begins moving all over the place, as opposed to staying in tact with a fixed width.

For example, if you have a mobile iOS device, open the default clock app that is shipped with it and use your stopwatch. You'll notice that each character in the 00:00:00 series has a fixed width, or at least it seems that way. If one of the 0 turns into a 1, even though 1 is seemingly smaller in width, it still fills up the same amount of space and thus the text does not jump all over the place.

In my React Native app, however, this is not the case. 1 takes up less width than 0 or any other number, so it makes the text jump all over the place and it's really annoying.

Here is a good, working version (notice how on each change of a number, the width of the 'container' that the number is in never changes?) This ensures a smooth transition:

enter image description here

Now take a look at my version, a disaster:

enter image description here

I can't seem to find a solution to this.

I feel like one way to solve this would be to have each character in a separate <Text> tag with a set width, but I know that would be completely overkill. There must be an easier way to do this.

Any guidance would be appreciated.

like image 661
Lansana Camara Avatar asked Aug 13 '16 13:08

Lansana Camara


People also ask

How do I fix text size in React Native?

You need to use fontSize attribute/property of stylesheet design, in order to set text font size in your Text component. Set Fontsize in react native application : Using below CSS properties you can set font size in your react native application.

How do I change the width of a percentage in React Native?

To set width style to a percentage number with React Native, we can use flexbox. to set flexDirection to 'row' to add a horizontal flexbox layout. We set the 2nd Text component to fill 20% of the screen. Then we set flexGrow to 1 on the first Text component to expand to fill the remaining width of the screen.

How do you use height and width in React Native?

import { Dimensions } from 'react-native'; You can get the application window's width and height using the following code: const windowWidth = Dimensions. get('window').


2 Answers

The system font in iOS is San Francisco, which has proportional numbers by default but contains an option for fixed-width (monospaced) numbers. With react-native, you have to use the fontVariant property on your Text component's style:

<Text style={{fontVariant: ['tabular-nums']}}>   1,234,567,890.12 </Text> 

I had a hard time finding it because the name isn't explicit and not what is typically used. Here's a link to the the Text props on the RN doc: https://facebook.github.io/react-native/docs/text.html#style

like image 122
Ethan O. Avatar answered Oct 19 '22 19:10

Ethan O.


Although the question is tagged for iOS, in case anyone is looking for a generic solution that supports monospace text on both iOS and Android (like I was), then here's an additional resource for you!

Font selection:

react-native-training/react-native-fonts on GitHub has a good list of fonts which are on each platform. As you can see, there is no overlap between the monospace fonts which OP provided in their answer. However, Android has a font called 'monospace' which will work for this use case.

OS Conditional statement

Since react native will throw an error if a font in fontFamily does not exist, we will need to conditionally set the fontFamily based on what's available in the OS. Platform.OS from react-native can be used to determine the device OS.

Example

// components/TextFixedWidth.js import React from 'react' import { Platform, Text } from 'react-native'  export default function TextFixedWidth ({ children }) {   const fontFamily = Platform.OS === 'ios' ? 'Courier' : 'monospace'    return (       <Text style={{fontFamily}}>{ children }</Text>   ) } 

Then

// in a render method somewhere in the app <TextFixedWidth>   Any monospace text you want! </TextFixedWidth> 

I hope this is helpful :)

like image 37
Julian Soro Avatar answered Oct 19 '22 17:10

Julian Soro