react-native-asset icon indicating copy to clipboard operation
react-native-asset copied to clipboard

Improve Android fonts linking process

Open fabioh8010 opened this issue 1 year ago • 7 comments

This PR aims to improve the whole Android fonts linking process.

Problem

Currently, during Android linking, font assets are copied to Android asset's folder and then can be used in the application. The problem is that in RN Android has a different logic to manage fonts related to iOS, requiring the developer to rely on the font file's name to be able to use the font properly in the application.

To give an example, let's say I added Lato font to my project and linked the files in both Android and iOS platforms. These are the Lato font files:

  • Lato-Black.ttf
  • Lato-BlackItalic.ttf
  • Lato-Bold.ttf
  • Lato-BoldItalic.ttf
  • Lato-Italic.ttf
  • Lato-Light.ttf
  • Lato-LightItalic.ttf
  • Lato-Regular.ttf
  • Lato-Thin.ttf
  • Lato-ThinItalic.ttf

For iOS, I can simply use a combination of fontFamily, fontWeight and fontStyle styles to select the desired font:

<Text style={{ fontFamily: 'Lato', fontWeight: '700', fontStyle: 'italic' }}>Lato 700 Italic</Text>

For Android, this approach won't work and you have to rely on the font's name in order to select the desired font.

<Text style={{ fontFamily: 'Lato-BoldItalic' }}>Lato 700 Italic</Text>

Developers end up having to use different approaches in order to custom fonts work properly for both platforms.

Solution

This PR solves the stated problem by changing the Android linking process to do the steps described in this guide automatically. In Android, fonts are now going to be managed by using XML Fonts to handle all font's variants.

During font assets copying process, here is the following logic:

  1. Read all font assets and create a font family map, where each entry is a different font family with its corresponding font files and its styles / weights.
  2. For each entry in the font family map:
    1. Create a new XML Font file or edit an existing one, replacing already defined entries and style / weight duplicates.
    2. Copy the font files to res/font/ folder and normalize their names.
    3. Add ReactFontManager's import to MainApplication.java file if it isn't declared yet.
    4. Add a method call inside onCreate() to load the custom font on Android.

During font assets cleaning process, here is the following logic:

  1. For each deleted font file, locate the corresponding one in res/font folder that needs to be deleted.
  2. Create a font family map, where each entry is a different font family with its corresponding font files.
  3. For each entry in the font family map:
    1. Remove the font entries in the corresponding font family XML file.
    2. If the XML file is empty, remove the file and the method call in MainApplication.java.
    3. If there is no usages of ReactFontManager in MainApplication.java, remove the import as well.

fabioh8010 avatar Apr 28 '23 07:04 fabioh8010

@unimonkiez Thanks for your review! About the migration, even if I implement it won't be 100% seamless as it would require changes in the application as well, specifically how the developer use fontFamily, fontStyle and fontWeight. One thing we could do is display a message in the terminal explaining about the migration made and the necessary steps to update application's code as well, maybe even with a link to a doc file or something. WDYT?

fabioh8010 avatar May 17 '23 14:05 fabioh8010

@unimonkiez Thanks for your review! About the migration, even if I implement it won't be 100% seamless as it would require changes in the application as well, specifically how the developer use fontFamily, fontStyle and fontWeight. One thing we could do is display a message in the terminal explaining about the migration made and the necessary steps to update application's code as well, maybe even with a link to a doc file or something. WDYT?

Sounds excellent !

unimonkiez avatar May 18 '23 07:05 unimonkiez

@unimonkiez I updated the PR with the following changes:

  • Addressed the requested changes
  • Implemented a migration for the new Android font linking logic. Tested with edge cases as well e.g. migrating while adding/removing fonts
  • Added documentation and fixed some typos
  • Improved font italic detection logic to cover an edge case

Changes: https://github.com/unimonkiez/react-native-asset/pull/52/files/5952050efc5ab27f4592a85ce5ba843ce56d65c0..a902630a1313c3a0c6116937e0a2f56cf9f0215c

fabioh8010 avatar May 20 '23 21:05 fabioh8010

Hi @unimonkiez , did you have a chance to take a look at the latest changes on this PR? Thanks!

fabioh8010 avatar Jun 02 '23 16:06 fabioh8010

Hi @unimonkiez, just bringing this PR to your attention again, I appreciate any feedback or action you could take. Thanks!

fabioh8010 avatar Jul 01 '23 16:07 fabioh8010

@unimonkiez thanks for your reviews of this pull request so far. We'd love to help push this feature forward in whatever way we can 🙂

roryabraham avatar Aug 07 '23 19:08 roryabraham

Thanks for your work @fabioh8010 and @unimonkiez It works really well.

If anyone wants to use it now:

  1. Uninstall any previous version
npm uninstall -g react-native-asset
npm uninstall -D react-native-asset
  1. Install version from fabioh8010
npm i -D github:fabioh8010/react-native-asset#feature/android-font-family-improvement

Vi-dot avatar Aug 11 '23 22:08 Vi-dot