custom fonts support The Android Way (#24595)
Summary: In https://github.com/facebook/react-native/pull/23865, RN introduced support for custom fonts the Android Way. But it introduced performance regression because it'll lookup for a font using getIdentifier() every time fontFamily changed. This PR fixes regression by requiring custom fonts to be listed in **fonts** array, and populating **mTypeCache** at first use using the list. [Android] [Changed] - Require custom fonts to list in **fonts** array. Fixes performance regression. Pull Request resolved: https://github.com/facebook/react-native/pull/24595 Reviewed By: mdvacca Differential Revision: D15184590 Pulled By: fkgozali fbshipit-source-id: e3feb2396609583ebc95101130186a1f5af931da
This commit is contained in:
Родитель
661b3b63ec
Коммит
fd6386a07e
|
@ -8,7 +8,6 @@
|
|||
|
||||
package com.facebook.react.uiapp;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.ReactActivity;
|
||||
|
|
|
@ -15,12 +15,11 @@ import com.facebook.react.ReactApplication;
|
|||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.facebook.react.views.text.ReactFontManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RNTesterApplication extends Application implements ReactApplication {
|
||||
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||
@Override
|
||||
|
@ -29,7 +28,7 @@ public class RNTesterApplication extends Application implements ReactApplication
|
|||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getBundleAssetName() {
|
||||
public String getBundleAssetName() {
|
||||
return "RNTesterApp.android.bundle";
|
||||
}
|
||||
|
||||
|
@ -46,6 +45,12 @@ public class RNTesterApplication extends Application implements ReactApplication
|
|||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
ReactFontManager.getInstance().addCustomFont(this, "Srisakdi", R.font.srisakdi);
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<font app:fontStyle="normal" app:fontWeight="400" app:font="@font/srisakdi_regular"/>
|
||||
<font app:fontStyle="normal" app:fontWeight="700" app:font="@font/srisakdi_bold" />
|
||||
</font-family>
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -182,6 +182,14 @@ class TextExample extends React.Component<{}> {
|
|||
<Text style={{fontFamily: 'notoserif', fontStyle: 'italic'}}>
|
||||
NotoSerif Italic (Missing Font file)
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Srisakdi'}}>Srisakdi Regular</Text>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: 'Srisakdi',
|
||||
fontWeight: 'bold',
|
||||
}}>
|
||||
Srisakdi Bold
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</RNTesterBlock>
|
||||
|
|
|
@ -7,14 +7,15 @@
|
|||
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.text.TextPaint;
|
||||
import android.text.style.MetricAffectingSpan;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
|
||||
|
||||
/**
|
||||
|
@ -39,7 +40,7 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
|
|||
int fontStyle,
|
||||
int fontWeight,
|
||||
@Nullable String fontFamily,
|
||||
AssetManager assetManager) {
|
||||
@NonNull AssetManager assetManager) {
|
||||
mStyle = fontStyle;
|
||||
mWeight = fontWeight;
|
||||
mFontFamily = fontFamily;
|
||||
|
@ -52,7 +53,7 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateMeasureState(TextPaint paint) {
|
||||
public void updateMeasureState(@NonNull TextPaint paint) {
|
||||
apply(paint, mStyle, mWeight, mFontFamily, mAssetManager);
|
||||
}
|
||||
|
||||
|
@ -116,5 +117,4 @@ public class CustomStyleSpan extends MetricAffectingSpan implements ReactSpan {
|
|||
}
|
||||
paint.setSubpixelText(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,15 +7,18 @@
|
|||
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
|
||||
/**
|
||||
* Class responsible to load and cache Typeface objects. It will first try to load typefaces inside
|
||||
* the assets/fonts folder and if it doesn't find the right Typeface in that folder will fall back
|
||||
|
@ -36,10 +39,12 @@ public class ReactFontManager {
|
|||
|
||||
private static ReactFontManager sReactFontManagerInstance;
|
||||
|
||||
private Map<String, FontFamily> mFontCache;
|
||||
final private Map<String, FontFamily> mFontCache;
|
||||
final private Map<String, Typeface> mCustomTypefaceCache;
|
||||
|
||||
private ReactFontManager() {
|
||||
mFontCache = new HashMap<>();
|
||||
mCustomTypefaceCache = new HashMap<>();
|
||||
}
|
||||
|
||||
public static ReactFontManager getInstance() {
|
||||
|
@ -49,8 +54,7 @@ public class ReactFontManager {
|
|||
return sReactFontManagerInstance;
|
||||
}
|
||||
|
||||
public
|
||||
@Nullable Typeface getTypeface(
|
||||
public @Nullable Typeface getTypeface(
|
||||
String fontFamilyName,
|
||||
int style,
|
||||
AssetManager assetManager) {
|
||||
|
@ -60,6 +64,13 @@ public class ReactFontManager {
|
|||
mFontCache.put(fontFamilyName, fontFamily);
|
||||
}
|
||||
|
||||
if(mCustomTypefaceCache.containsKey(fontFamilyName)) {
|
||||
return Typeface.create(
|
||||
mCustomTypefaceCache.get(fontFamilyName),
|
||||
style
|
||||
);
|
||||
}
|
||||
|
||||
Typeface typeface = fontFamily.getTypeface(style);
|
||||
if (typeface == null) {
|
||||
typeface = createTypeface(fontFamilyName, style, assetManager);
|
||||
|
@ -71,6 +82,20 @@ public class ReactFontManager {
|
|||
return typeface;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method allows you to load custom fonts from res/font folder as provided font family name.
|
||||
* Fonts may be one of .ttf, .otf or XML (https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml).
|
||||
* To support multiple font styles or weights, you must provide a font in XML format.
|
||||
*
|
||||
* ReactFontManager.getInstance().addCustomFont(this, "Srisakdi", R.font.srisakdi);
|
||||
*/
|
||||
public void addCustomFont(@NonNull Context context, @NonNull String fontFamily, int fontId) {
|
||||
Typeface font = ResourcesCompat.getFont(context, fontId);
|
||||
if (font != null) {
|
||||
mCustomTypefaceCache.put(fontFamily, font);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional font family, or replace the exist one in the font memory cache.
|
||||
* @param style
|
||||
|
|
Загрузка…
Ссылка в новой задаче