Summary:
Abstract class `ReactBaseTextShadowNode` was decoupled from `ReactTextShadowNode` to separate two goals/roles:
* `ReactBaseTextShadowNode` represents spanned `<Text>` nodes, which can bear text attributes (both `RCTText` and `RCTVirtualText`);
* `ReactTextShadowNode` represents anchor `<Text>` view in Yoga terms, which can bear layout attributes (`RCTText` and `RCTTextInput`).
`ReactVirtualTextShadowNode` now inherits `ReactBaseTextShadowNode`.
The same architectural changes was applited to view managers.
Why?
* This is just a better architecture which represents the nature of this objects.
* Bunch of "negative" logic which turn off excessive features for some suclasses was removed.
* Memory efficiency.
* Now we can improve `<TextInput>` component using right inheritance. Yay!
Reviewed By: achen1
Differential Revision: D5715830
fbshipit-source-id: ecc0764a03b5b7586fe77ad31f149cd840f4da41
Summary:
ReactRawTextShadowNode represents "raw" text node (aka textContent), so it cannot have layout or styling, it is just a line of text, a pure string.
So, we must not interit it from HUGE ReactTextShadowNode (which represents <Text> node with ReactRawTextShadowNode instance inside).
We need this change to make future fancy (and valuable from product perspective) refactoring possible. Stay tuned!
Reviewed By: achen1
Differential Revision: D5712961
fbshipit-source-id: 009e48046bdf34ddfd40b93175934969af64b98b
Summary:
Overview -
This PR resolves the issue described in #14606. This PR makes Text components take into account the includeFontPadding property when calculating their size.
Background -
Currently, on Android, when includeFontPadding is set to false, the React Text component does not adjust its height. This makes it difficult to lay out other components at a precise spacing relative to a Text component.
iOS calculates the height of a UILabel based on the font's descent + ascent.
Android lets you choose whether to calculate the height of a TextView based on the font's top + bottom (includeFontPadding=true) or ascent + descent (includeFontPadding=false).
In order for a text component to be the same size on iOS and Android (relative to the rest of the layout in points and dips), one should set includeFontPadding=false on Android - but the React Text component needs to take this property into account when sizing itself for this to work.
Please see this stack overflow post for a visual explanation of the difference between a font's ascent/descent and top/bottom - https://stackoverflow.com/questions/27631736/meaning-of-top-ascent-baseline-descent-bottom-and-leading-in-androids-font
Testing -
Please see the attached screenshots to see the height difference of a Text component with this PR when includeFontPadding is true vs false.
The font I am using has an ascent + descent = em-size so that the height of the Text component will be equal to the font-size for a single line of text. This is to clearly show the additional height that includeFontPadding=true adds to the Text component.
For Text components that are styled in the same way,
When includeFontPadding=true, height = ~29.714 dips
When includeFontPadding=false, height= 24 dips
<img width="342" alt="includefontpaddingtrue" src="https://user-images.githubusercontent.com/1437344/27299391-3eec9de0-54fa-11e7-81d5-d0aeb40e8e27.png">
<img width="346" alt="includefontpaddingfalse" src="https://user-images.githubusercontent.com/1437344/27299401-45c95248-54fa-11e7-98d7-17dd152d3cb8.png">
Closes https://github.com/facebook/react-native/pull/14609
Reviewed By: AaaChiuuu
Differential Revision: D5587602
Pulled By: achen1
fbshipit-source-id: 6d2f12ba72ec7462676645519cd27820279278eb
Summary:
Make android-version accept a decimal
number as lineHeight.
Credits where due, solution was given in this
issue: facebook/react-native#10607
According to the w3 spec the property
line-height should accept decimal values
(and it does on iOS) but the android
version has the wrong data-type for the
shadowed method, resulting in a stacktrace
saying:
com.facebook.react.bridge.UnexpectedNativeTypeException: TypeError:
expected dynamic type `int64', but had type `double'
Setting it to a float makes it accept
decmial values as it should.
* Create an app without this commit and create the same app with this commit:
In both apps:
- Leave line-height undefined. Behavior is unaffected by this commit.
- Set lineHeight to a integer number. Behavior is unaffected by this commit.
- Set lineHeight to a decimal number. Line height is now rendered with decimals in the app with this fix.
* Run android integration tests to see nothing
else broke.
Sign the [CLA][2], if you haven't already.
Small pull requests are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it.
Make sure all **tests pass** on both [Travis][3] and [Circle CI][4]. PRs that break tests are unlikely to be merged.
For more info, see the ["Pull Requests"][5] section of our "Contributing" guidelines.
[1]: https://medium.com/martinkonicek/what-is-a-test-plan-8bfc840ec171#.y9lcuqqi9
[2]: https://code.facebook.com/cla
[3]: https://travis-ci.org/facebook/react-native
[4]: http://circleci.com/gh/facebook/react-native
[5]: https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md#pull-requests
Closes https://github.com/facebook/react-native/pull/13843
Differential Revision: D5152982
Pulled By: shergin
fbshipit-source-id: cda3b72497a6c27d6948b31ec846640a8913775a
Summary:
Inspired by #13191
Creating a test app with spannable `TextView`, and observe the text width/height
Closes https://github.com/facebook/react-native/pull/13203
Differential Revision: D4795809
Pulled By: hramos
fbshipit-source-id: a7c6845abe7472dc7ad2f1f978a20d02fe49eda8
Summary:
Bug in Android https://code.google.com/p/android/issues/detail?id=33868 causes the RN catalyst instrumentation test to fail with
```
java.lang.ArrayIndexOutOfBoundsException: length=253; index=-1
at android.text.StaticLayout.calculateEllipsis(StaticLayout.java:667)
at android.text.StaticLayout.out(StaticLayout.java:631)
at android.text.StaticLayout.generate(StaticLayout.java:423)
...
```
The fix is to set singleLine to true when there is only one line of text
Reviewed By: AaaChiuuu
Differential Revision: D4562000
fbshipit-source-id: 84248e3982063b767e8b0465effe2321b54a7fa2
Summary:
Fixes#11592
This bug was seen on a Galaxy S4 running Android 4.4.2. On this device, Android's `Layout.getDesiredWidth` method doesn't correctly measure text that contains unicode emoticons. It appears to think the emoticons take up 0 space.
Setting ANTI_ALIAS_FLAG in the TextPaint's constructor instead of setting it later with setFlags works around the Android bug.
**Test plan (required)**
My team uses this fix in our app.
Adam Comella
Microsoft Corp.
Closes https://github.com/facebook/react-native/pull/12690
Differential Revision: D4673649
Pulled By: mkonicek
fbshipit-source-id: 535f371281927bfff5d8b42966496bc8daf30045
Summary:
A copy of https://github.com/facebook/react-native/pull/7791 because of our very imperfect tools that mirror the changes from pull requests in the fb monorepo. The internal Phabricator revision for #7791 is in an 'abandoned' state (by foghina probably because of changing teams) and Phabricator doesn't allow me to claim that revision and merge it. Therefore I'm creating a new one.
(It's not foghina's fault, no one probably knew about this "abandoned Phabricator revision" edge case, don't remember we hit it before.)
Will try to keep attribution (git blame) to rigdern when merging.
Closes https://github.com/facebook/react-native/pull/12448
Differential Revision: D4584743
Pulled By: mkonicek
fbshipit-source-id: 66e5b88134fca1980adc4cd8a2ff17c42e10022c
Summary:
Android has a text API called breakStrategy for controlling how paragraphs are broken up into lines. For example, some modes support automatically hyphenating words so a word can be split across lines while others do not.
One source of complexity is that Android provides different defaults for `breakStrategy` for `TextView` vs `EditText`. `TextView`'s default is `BREAK_STRATEGY_HIGH_QUALITY` while `EditText`'s default is `BREAK_STRATEGY_SIMPLE`.
In addition to exposing `textBreakStrategy`, this change also fixes a couple of rendering glitches with `Text` and `TextInput`. `TextView` and `EditText` have different default values for `breakStrategy` and `hyphenationFrequency` than `StaticLayout`. Consequently, we were using different parameters for measuring and rendering. Whenever measuring and rendering parameters are inconsistent, it can result in visual glitches such as the text taking up too much space or being clipped.
This change fixes these inconsistencies by setting `breakStrategy` and `hyphenat
Closes https://github.com/facebook/react-native/pull/11007
Differential Revision: D4227495
Pulled By: lacker
fbshipit-source-id: c2d96bd0ddc7bd315fda016fb4f1b5108a2e35cf
Summary:
The reason for this change is to implement `allowFontScaling` on the Android's React Native Text component. Prior to this PR `allowFontScaling` only works for iOS.
The following link contains images of `allowFontScaling` working in Android on small, normal, large, and huge system fonts (from native Android display settings)
http://imgur.com/a/94bF1
The following link is a video of the same thing working on an Android emulator
https://youtu.be/1jTlZhPdj9Y
Here is the sample code snippet driving the video/images
```
render() {
const size = [12, 14, 16, 18];
return (
<View style={{backgroundColor: 'white', flex: 1}}>
<Text>
Default size no allowFontScaling prop (default true)
</Text>
<Text allowFontScaling={true}>
Default size allowFontScaling: true
</Text>
<Text style={{ marginBottom: 10, }} allowFontScaling={false}>
Default size allowFontScaling: false
</Text>
{ size.map(
Closes https://github.com/facebook/react-native/pull/10898
Differential Revision: D4335190
Pulled By: lacker
fbshipit-source-id: 0480809c44983644ff2abfcaf4887569b2bfede5
Summary:
By default Android will put extra space above text to allow for upper-case accents or other ascenders. With some fonts, this can make text look slightly misaligned when centered vertically.
We have found that the effect is very noticeable with certain custom fonts on Android. On iOS the font aligns vertically as expected.
Android exposes a property `includeFontPadding` that will remove this extra padding if set to false. This PR exposes that to JS, and adds it to the documentation and UIExplorer.
Closes https://github.com/facebook/react-native/pull/9323
Differential Revision: D4266713
Pulled By: lacker
fbshipit-source-id: f9711254bc26c09b4586a865f0e95ef4bf77cf3f
Summary:
Virtual shadow nodes (e.g. text) don't use CSSNodes so we don't need to create them. This shows large savings in CSSNodes allocated, depending on the app.
This could be breaking if:
- You have virtual nodes that still set and get CSS properties. The setters now no-op for virtual nodes (I unfortunately couldn't remove them completely -- see the comment on LayoutShadowNode), but the getters will NPE. If you see these NPE's, you should almost definitely be using your own datastructure instead of a CSSNode as virtual nodes will not participate in the layout process (and the CSSNode is then behaving just as a POJO for you).
I do not anticipate this to be breaking for anyone, but am including breaking in the commit message since this is a change in API contract.
Reviewed By: emilsjolander
Differential Revision: D4220204
fbshipit-source-id: b8dc083fff420eb94180f669dd49389136111ecb
Summary:
Moves from CSSNodeDEPRECATED to CSSNode. This has shown to be a huge performance win for layout time within FB.
This is BREAKING because CSSNode contains bug fixes that were not migrated to CSSNodeDEPRECATED which may change the way your layout appears. The most common of these by far involves `flex: 1`.
Previously, developers had to put `flex: 1` in many places it didn't belong in order to work around a bug in css-layout. Now `flex: 1` is treated properly and, unfortunately, this means that your layout may no longer look correct. Specifically, you may see that your layout looks collapsed, or children don't render. The fix is to simply remove `flex: 1` from those containers.
Reviewed By: emilsjolander
Differential Revision: D3992787
fbshipit-source-id: 7a3a2a34a8941c0524e6ba3c5379e434d3e03247
Summary:
This diff makes it so ReactShadowNode holds a CSSNode instead of extending one. This will enable us to pool and re-use CSSNodes and will allow us to keep from breaking the CSSNode api assumption that nodes that have measure functions don't have children (right now, text nodes have measure functions, but they also have raw text children).
BREAKING
This diff makes ReactShadowNode no longer extend CSSNodeDEPRECATED. If you have code that depended on that, e.g. via instanceof checks, that will no longer work as expected. Subclasses that override getChildAt/addChildAt/etc will need to update your method signatures. There should be no runtime behavior changes.
Reviewed By: emilsjolander
Differential Revision: D4153818
fbshipit-source-id: 2836434dd925d8e4651b9bb94b602c235e1e7665
Summary:
The issue here is that on some devices (ie. Nexus 5X), under certain
circumstances, the text gets trimmed. A simple example is P56651885, where the
text is at the end of the line and some padding is set. Digging further with
P56659346, I found that only the paddings that have integer pixel values work
correctly: these are the values P56656483, and this is the screenshot of that
test: {F63510378}.
It turns out that when we set the padding directly on the TextView, we have to
convert from float to int, and use `ceil` in the process. We lose some precision
here, since the csslayout will use the float values to compute the layout of the
views. The ideal solution would be to just set the float values on the TextView,
but since we can't do that, we should avoid using `ceil` instead of `floor`
since it can have bad side-effects in some scenarios.
Going way back to D1881202 and D1710471, we started using `ceil` because that
is how android handles non-integer
density ratios: "This figure is the factor by which you should multiply the dp
units on order to get the actual pixel count for the current screen. (Then add
0.5f to round the figure up to the nearest whole number, when converting to an
integer.)", see https://developer.android.com/guide/practices/screens_support.html.
Reviewed By: emilsjolander
Differential Revision: D3876310
fbshipit-source-id: 701c05a8b1a045d4e06fc89ffe79162c1eecb62c
Summary:
Setting the line height with the help of Android-provided StaticLayout is incorrect. A
simple example app will display the following when `setLineSpacing(50.f, 0.f)`
is set: {F62987699}. You'll notice that the height of the first line is a few
pixels shorter than the other lines.
So we use a custom LineHeightSpan instead, which needs to be applied to the text
itself, and no height-related attributes need to be set on the TextView itself.
Reviewed By: lexs
Differential Revision: D3841658
fbshipit-source-id: 7257df4f1b2ce037554c7a7a5ca8f547a2056939
Summary:
Currently, `<Text>` and `<TextInput>` components on Android do not support borders.
This change adds support for the borderRadius, borderColor, and
borderWidth props on the `<Text>` and `<TextInput>` components on Android.
ReactViewGroup already implements this functionality so
we copied its implementation over into the ReactTextView
and ReactEditText classes.
**Test plan (required)**
Verified that the various border props work on Text and TextInput components in a test app.
Adam Comella
Microsoft Corp.
Closes https://github.com/facebook/react-native/pull/9658
Differential Revision: D3819993
Pulled By: lexs
fbshipit-source-id: 183b0aa95369dd781f03b5a1f0f409ab47284e39
Summary:
There are a couple of buggy behaviors in the current implementation of the `ellipsizeMode` prop on Android:
- Setting the `numberOfLines` prop stomps on whatever value you provided for `ellipsizeMode` earlier.
- The value you've provided for `ellipsizeMode` is used even if you've configured your view to have an unlimited size (i.e. `numberOfLines` is 0 or unspecified).
This change fixes these issues which makes Android's `ellipsizeMode` prop more consistent with iOS's. Additionally, it renames LineBreakMode to EllipsizeMode in a couple of places.
**Test plan (required)**
Verified that the `numberOfLines` and `ellipsizeMode` props work correctly in an Android test app.
Adam Comella
Microsoft Corp.
Closes https://github.com/facebook/react-native/pull/9594
Differential Revision: D3810166
Pulled By: foghina
fbshipit-source-id: 229c9bfc3ef10670a1090311ea9d095cb2c1121a
Summary:
Setting the line height with the help of Android-provided StaticLayout is incorrect. A
simple example app will display the following when `setLineSpacing(50.f, 0.f)`
is set: {F62987699}. You'll notice that the height of the first line is a few
pixels shorter than the other lines.
So we use a custom LineHeightSpan instead, which needs to be applied to the text
itself, and no height-related attributes need to be set on the TextView itself.
Reviewed By: lexs
Differential Revision: D3751097
fbshipit-source-id: 6c5a8d01a6dca4ff6eef9c3aadd1b550054432d2
Summary:
Setting the line height with the help of Android-provided StaticLayout is incorrect. A
simple example app will display the following when `setLineSpacing(50.f, 0.f)`
is set: {F62987699}. You'll notice that the height of the first line is a few
pixels shorter than the other lines.
So we use a custom LineHeightSpan instead, which needs to be applied to the text
itself, and no height-related attributes need to be set on the TextView itself.
Reviewed By: lexs
Differential Revision: D3751097
fbshipit-source-id: c3574a1080efec26436a5c61afbff89afa8679e7
Summary:
**Motivation**
For the `Text` component, if `numberOfLines` is set to `0`, the behavior on iOS is such that there is no limit.
On Android, the behavior is such that `numberOfLines={0}` will not render the `Text` component.
Since we want behavior to be the same across platforms, this change will make sure Android behaves the same as iOS.
**Test Plan**
Create a `Text` component specifying `numberOfLines={0}` on an Android project.
Expected:
- `Text` component displays, with no limit to number of lines.
Result:
- `Text` component does not appear at all.
Closes https://github.com/facebook/react-native/pull/9188
Differential Revision: D3697115
fbshipit-source-id: c1768ac22bab3c0e41a9df38b7314f3201512eb2
Summary:
Since the core layout in RN is now assigning `left/right` to `start/end`, we need to tweak the text input handling as well:
1. We need to replace all left/right to start/end
2. For text inset padding, we need to manually flipped the padding in RTL situation.
Reviewed By: fkgozali
Differential Revision: D3670277
fbshipit-source-id: 442bead25af8548a85dd1f359aa5a799982d1185
Summary: Use UNSET(-1) as default will lead wrong calculation for text alignment. Change it to Gravity.NO_GRAVITY to fix this problem.
Reviewed By: fkgozali
Differential Revision: D3624417
fbshipit-source-id: c116560e64600be60b2fe719f575701b00f20a97
Summary: Change the textalign setter to support RTL. In order to support text alignment according to layout style, move the textalign setter bridge function from ReactTextViewManager.java to ReactTextShadowNode.java and calculate it correctly on RCTTextUpdate.
Reviewed By: dmmiller
Differential Revision: D3597494
fbshipit-source-id: e5ca17b99b4233cc49a447a34175473e339ff53d
Summary:
lineBreakMode only in rc so I think we can replace property without any deprecation warnings. satya164
Closes https://github.com/facebook/react-native/pull/9008
Differential Revision: D3614901
fbshipit-source-id: 724227c0a89192825a24850b930b80884571a51f
Summary:
This PR was split from a commit originally in #8619. /cc dmmiller
When an inline image was larger than the specified line height,
the image would be clipped. This changes the behavior so
that the line height is changed to make room for the inline
image. This is consistent with the behavior of RN for iOS.
Here's how the change works.
ReactTextView now receives its line height from the layout thread
rather than directly from JavaScript.
The reason is that the layout thread may pick a different line height.
In the case that the tallest inline image is larger than the line
height supplied by JavaScript, we want to use that image's height as
the line height rather than the supplied line height.
Also fixed a bug where the image, which is supposed to be baseline
aligned, would be positioned at the wrong y location. To fix this,
we use `y` (the baseline) in the `draw` method rather than trying
to calculate the baseline from `bottom`. For more information
see https://code.google.com/p/andro
Closes https://github.com/facebook/react-native/pull/8907
Differential Revision: D3592781
Pulled By: dmmiller
fbshipit-source-id: cba6cd86eb4e3abef6a0d7a81f802bdb0958492e
Summary: D3516692 incorrectly assumed that the Spacing object was immutable. This is not true as it can change in a measure pass on the shadow thread while the UI is displaying some other data. This fixes it to just pull the values we need and pass them instead of the object.
Reviewed By: foghina
Differential Revision: D3523004
fbshipit-source-id: 056baecf60a9c2f2494d173a3c60396a93b97d42
Summary: Text was not correctly respecting padding. We would account for it when measuring, but then not actually apply the padding to the text. This adds support for proper padding
Reviewed By: andreicoman11
Differential Revision: D3516692
fbshipit-source-id: 9a0991d89e9194c0e87af0af56c6631a6b95700a