fontFamily, fontStyle and fontWeight support for TextInput

Summary:
fontFamily, fontWeight and fontStyle properties are being ignored for TextInput.

There's an additional issue that happens when you add secureTextEntry={true}  it overrides the current font preferences (because it defaults to monospace) so we have to reapply it.
Master right now:

![screen shot 2016-03-21 at 6 21 05 pm](https://cloud.githubusercontent.com/assets/1247834/13936110/c25ffea8-ef91-11e5-8d71-1b0a55184e24.png)

Demo after the fix:

![5ux4bpjfwh](https://cloud.githubusercontent.com/assets/1247834/13935865/0f2ca8be-ef90-11e5-82c7-d5a2dd33b70e.gif)
Closes https://github.com/facebook/react-native/pull/6564

Differential Revision: D3081623

Pulled By: bestander

fb-gh-sync-id: 329cac6755b5a0dd549e546768f39efa7b7f4daa
fbshipit-source-id: 329cac6755b5a0dd549e546768f39efa7b7f4daa
This commit is contained in:
Bruno Barbieri 2016-04-28 13:21:57 -07:00 коммит произвёл Facebook Github Bot 9
Родитель 037e9ba945
Коммит 41e89b4129
4 изменённых файлов: 113 добавлений и 5 удалений

Просмотреть файл

@ -407,6 +407,31 @@ exports.examples = [
);
}
},
{
title: 'fontFamily, fontWeight and fontStyle',
render: function() {
return (
<View>
<TextInput
style={[styles.singleLine, {fontFamily: 'sans-serif'}]}
placeholder="Custom fonts like Sans-Serif are supported"
/>
<TextInput
style={[styles.singleLine, {fontFamily: 'sans-serif', fontWeight: 'bold'}]}
placeholder="Sans-Serif bold"
/>
<TextInput
style={[styles.singleLine, {fontFamily: 'sans-serif', fontStyle: 'italic'}]}
placeholder="Sans-Serif italic"
/>
<TextInput
style={[styles.singleLine, {fontFamily: 'serif'}]}
placeholder="Serif"
/>
</View>
);
}
},
{
title: 'Passwords',
render: function() {

Просмотреть файл

@ -279,6 +279,9 @@ public class ReactTextShadowNode extends LayoutShadowNode {
/**
* Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
* return the weight.
*
* This code is duplicated in ReactTextInputManager
* TODO: Factor into a common place they can both use
*/
private static int parseNumericFontWeight(String fontWeightString) {
// This should be much faster than using regex to verify input and Integer.parseInt
@ -407,13 +410,17 @@ public class ReactTextShadowNode extends LayoutShadowNode {
markUpdated();
}
}
@ReactProp(name = ViewProps.FONT_FAMILY)
public void setFontFamily(@Nullable String fontFamily) {
mFontFamily = fontFamily;
markUpdated();
}
/**
/* This code is duplicated in ReactTextInputManager
/* TODO: Factor into a common place they can both use
*/
@ReactProp(name = ViewProps.FONT_WEIGHT)
public void setFontWeight(@Nullable String fontWeightString) {
int fontWeightNumeric = fontWeightString != null ?
@ -430,7 +437,11 @@ public class ReactTextShadowNode extends LayoutShadowNode {
markUpdated();
}
}
/**
/* This code is duplicated in ReactTextInputManager
/* TODO: Factor into a common place they can both use
*/
@ReactProp(name = ViewProps.FONT_STYLE)
public void setFontStyle(@Nullable String fontStyleString) {
int fontStyle = UNSET;

Просмотреть файл

@ -16,6 +16,7 @@ import java.util.ArrayList;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.Typeface;
import android.text.Editable;
import android.text.InputType;
import android.text.SpannableStringBuilder;
@ -206,9 +207,12 @@ public class ReactEditText extends EditText {
@Override
public void setInputType(int type) {
Typeface tf = super.getTypeface();
super.setInputType(type);
mStagedInputType = type;
// Input type password defaults to monospace font, so we need to re-apply the font
super.setTypeface(tf);
// We override the KeyListener so that all keys on the soft input keyboard as well as hardware
// keyboards work. Some KeyListeners like DigitsKeyListener will display the keyboard but not
// accept all input from it

Просмотреть файл

@ -15,6 +15,7 @@ import java.util.LinkedList;
import java.util.Map;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
@ -64,7 +65,8 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
private static final String KEYBOARD_TYPE_NUMERIC = "numeric";
private static final String KEYBOARD_TYPE_PHONE_PAD = "phone-pad";
private static final InputFilter[] EMPTY_FILTERS = new InputFilter[0];
private static final int UNSET = -1;
@Override
public String getName() {
return REACT_CLASS;
@ -172,6 +174,58 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
(int) Math.ceil(PixelUtil.toPixelFromSP(fontSize)));
}
@ReactProp(name = ViewProps.FONT_FAMILY)
public void setFontFamily(ReactEditText view, String fontFamily) {
int style = Typeface.NORMAL;
if (view.getTypeface() != null) {
style = view.getTypeface().getStyle();
}
Typeface newTypeface = Typeface.create(fontFamily, style);
view.setTypeface(newTypeface);
}
/**
/* This code was taken from the method setFontWeight of the class ReactTextShadowNode
/* TODO: Factor into a common place they can both use
*/
@ReactProp(name = ViewProps.FONT_WEIGHT)
public void setFontWeight(ReactEditText view, @Nullable String fontWeightString) {
int fontWeightNumeric = fontWeightString != null ?
parseNumericFontWeight(fontWeightString) : -1;
int fontWeight = UNSET;
if (fontWeightNumeric >= 500 || "bold".equals(fontWeightString)) {
fontWeight = Typeface.BOLD;
} else if ("normal".equals(fontWeightString) ||
(fontWeightNumeric != -1 && fontWeightNumeric < 500)) {
fontWeight = Typeface.NORMAL;
}
if (fontWeight != view.getTypeface().getStyle()) {
view.setTypeface(view.getTypeface(), fontWeight);
}
}
/**
/* This code was taken from the method setFontStyle of the class ReactTextShadowNode
/* TODO: Factor into a common place they can both use
*/
@ReactProp(name = ViewProps.FONT_STYLE)
public void setFontStyle(ReactEditText view, @Nullable String fontStyleString) {
int fontStyle = UNSET;
if ("italic".equals(fontStyleString)) {
fontStyle = Typeface.ITALIC;
} else if ("normal".equals(fontStyleString)) {
fontStyle = Typeface.NORMAL;
}
Typeface currentTypeface = view.getTypeface();
if (currentTypeface == null) {
currentTypeface = Typeface.DEFAULT;
}
if (fontStyle != currentTypeface.getStyle()) {
view.setTypeface(currentTypeface, fontStyle);
}
}
@ReactProp(name = "onSelectionChange", defaultBoolean = false)
public void setOnSelectionChange(final ReactEditText view, boolean onSelectionChange) {
if (onSelectionChange) {
@ -391,6 +445,20 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
}
}
/**
* This code was taken from the method parseNumericFontWeight of the class ReactTextShadowNode
* TODO: Factor into a common place they can both use
*
* Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
* return the weight.
*/
private static int parseNumericFontWeight(String fontWeightString) {
// This should be much faster than using regex to verify input and Integer.parseInt
return fontWeightString.length() == 3 && fontWeightString.endsWith("00")
&& fontWeightString.charAt(0) <= '9' && fontWeightString.charAt(0) >= '1' ?
100 * (fontWeightString.charAt(0) - '0') : -1;
}
private static void updateStagedInputTypeFlag(
ReactEditText view,
int flagsToUnset,