question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Android Text elements that have adjustsFontSizeToFit do not have their font size adjusted when the height of a parent element is changed.

See original GitHub issue

Description

On Android, Text elements that have adjustsFontSizeToFit={true} do not have their font size adjusted when the height of a parent element is changed. This works as desired on iOS. This seems to be a defect in the excellent PR #26389 by @janicduplessis.

React Native version:

info Fetching system and libraries information...
System:
    OS: Windows 10 10.0.18362
    CPU: (12) x64 Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz
    Memory: 4.60 GB / 15.81 GB
  Binaries:
    Node: 10.17.0 - C:\Program Files\nodejs\node.EXE
    Yarn: Not Found
    npm: 6.11.3 - C:\Program Files\nodejs\npm.CMD
    Watchman: Not Found
  SDKs:
    Android SDK:
      API Levels: 27, 28, 29
      Build Tools: 28.0.3, 29.0.2
      System Images: android-27 | Google Play Intel x86 Atom, android-28 | Wear OS Intel x86 Atom, android-28 | Intel x86 Atom_64, android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-30 | Google APIs Intel x86 Atom
      Android NDK: Not Found
    Windows SDK: Not Found
  IDEs:
    Android Studio: Version  3.5.0.0 AI-191.8026.42.35.5791312
    Visual Studio: Not Found
  Languages:
    Java: 1.8.0_221
    Python: 2.7.16
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.13.1 => 16.13.1
    react-native: 0.63.4 => 0.63.4
    react-native-windows: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Steps To Reproduce

  1. Run the following app:
import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
export default class App extends React.Component {
  state = {
    rowHeight: 60,
  };

  render() {
    return (
      <View style={styles.container}>
        <View style={[styles.row, {height:this.state.rowHeight}]}>
          <Text adjustsFontSizeToFit numberOfLines={1} style={styles.paragraph}>
            Text text text text text text
          </Text>
        </View>
        <Text>{this.state.version}</Text>
        <View style={styles.button}>
         <Button onPress={() => this.setState({rowHeight: 10})} title="Set row height to 10"/>
        </View>
        <View style={styles.button}>
         <Button onPress={() => this.setState({rowHeight: 60})} title="Set row height to 60"/>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    paddingTop: 100,

  },
  row: {
    backgroundColor: 'lightblue',
    marginBottom: 20,
  },
  button: {
    margin: 10
  },
  paragraph: {
    fontSize: 100,
    fontWeight: 'bold',
    textAlign: 'center',
    backgroundColor: "yellow"
  },
});
  1. Press the button labeled “Set row height to 10”. Observe that on iOS the text’s font size is reduced but is unchanged on Android.

Expected Results

The font size of the Text element should be changed when the height of a parent element is changed on Android, consistent with iOS.

Snack, code example, screenshot, or link to a repository:

https://snack.expo.io/TAJyBmNdv

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:6

github_iconTop GitHub Comments

4reactions
janicduplessiscommented, Feb 24, 2021

I don’t think I tested changing the layout dynamically in the original PR. If someone can figure out a solution feel free to open a PR and I can have a look.

0reactions
fabriziobertoglio1987commented, Feb 24, 2021
how is layout.getHeight() calculated and why does it stop the iteration?

layout.getHeight() is the difference between

spacing = metrics.bottom - metrics.top;

First Time we render

<image src="https://user-images.githubusercontent.com/24992535/109019579-69bdb600-76b9-11eb-8200-cb2fa33e2b7e.png" height="150" />
boring: FontMetricsInt: top=-87 ascent=-76 descent=20 bottom=23 leading=0 width=971
layout.getHeight(): 110 

Second Time we render

<image src="https://user-images.githubusercontent.com/24992535/109019645-76420e80-76b9-11eb-8889-ba6bb686f60c.png" height="150" />
boring: FontMetricsInt: top=-40 ascent=-34 descent=9 bottom=11 leading=0 width=443
layout.getHeight(): 51

the value getHeight() is responsible for stopping the iteration which reduces the font weight

https://github.com/facebook/react-native/blob/7b09eb54e7ecdde91cb4748dc26207dd05088382/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java#L84-L85

how do we compute the new size of the text?

we add to the TextView a Span with the new font size and then measure the TextView https://github.com/facebook/react-native/blob/7b09eb54e7ecdde91cb4748dc26207dd05088382/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java#L92-L103

how does `BoringLayout` compute the height/width of the text?

The computation is done in init

    /* package */ void init(CharSequence source, TextPaint paint, Alignment align,
            BoringLayout.Metrics metrics, boolean includePad, boolean trustWidth) {
        int spacing;


        if (source instanceof String && align == Layout.Alignment.ALIGN_NORMAL) {
            mDirect = source.toString();
        } else {
            mDirect = null;
        }


        mPaint = paint;


        if (includePad) {
            spacing = metrics.bottom - metrics.top;
            mDesc = metrics.bottom;
        } else {
            spacing = metrics.descent - metrics.ascent;
            mDesc = metrics.descent;
        }


        mBottom = spacing;


        if (trustWidth) {
            mMax = metrics.width;
        } else {
            /*
             * If we have ellipsized, we have to actually calculate the
             * width because the width that was passed in was for the
             * full text, not the ellipsized form.
             */
            TextLine line = TextLine.obtain();
            line.set(paint, source, 0, source.length(), Layout.DIR_LEFT_TO_RIGHT,
                    Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null,
                    mEllipsizedStart, mEllipsizedStart + mEllipsizedCount);
            mMax = (int) Math.ceil(line.metrics(null));
            TextLine.recycle(line);
        }


        if (includePad) {
            mTopPadding = metrics.top - metrics.ascent;
            mBottomPadding = metrics.bottom - metrics.descent;
        }
    }

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to adjust font size to fit view in React Native for Android?
First, I wrapped my Text view inside a fixed size View, then I implement onLayout for both view, so that I can get...
Read more >
text-size-adjust - CSS: Cascading Style Sheets - MDN Web Docs
When an element containing text uses 100% of the screen's width, the algorithm increases its text size, but without modifying the layout. The...
Read more >
Text in Compose - Jetpack - Android Developers
Working with fonts. Text has a fontFamily parameter to allow setting the font used in the composable. By default, serif, sans ...
Read more >
Resize text layers – Figma Help Center
There are a few ways you can adjust the size of a text layer. ... Spell check is only disabled if you do...
Read more >
Increase default text size in Microsoft Edge
Learn how to change the font size and customize the style and size of fonts in Microsoft Edge.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found