Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Implement letterSpacing option #13199

Closed
wants to merge 3 commits into from
Closed

[Android] Implement letterSpacing option #13199

wants to merge 3 commits into from

Conversation

jerolimov
Copy link
Contributor

@jerolimov jerolimov commented Mar 29, 2017

Motivation

Implement letterSpacing option on Android. This was requested multiple times. (See also #3485 #10622) - This PR is inspired by #9420 but also fixes the layout calculation which is required for multiline text with letter spacing.

The problem with letter spacing on Android is, in general, that the API TextView#setLetterSpacing expects the letter spacing value in "EM", where "1 EM" is defined by the width of the letter 'M'. From the documentation: "Typical values for slight expansion will be around 0.05. Negative values will tighten text." The react-native developer expectation was that the spacing is defined in points, similar to width, height, margin, padding, and so on.

This patch implements an "approach" and calculates the "EM" based on the font size.

I tested this with the default font and the layout was now "similar" to iOS, but doesn't match the iOS layout exactly.

Test Plan

Screenshot on iOS (before and after):

simulator screen shot 29 mar 2017 12 16 17

Screenshot on Android before this patch:

2017-03-29 13 40 13

Screenshot on Android after this patch:

2017-03-29 13 34 09

Sourcecode for this "beautiful app" is available here: https://gist.github.com/jerolimov/39e4fd29702b6f1ad55768907d92c33d

Documentation Question

How can I update the documentation and remove the "ios" badge on the letterSpacing option?

@jerolimov jerolimov changed the title Implement letterSpacing option on Android. [Android] Implement letterSpacing option Mar 29, 2017
@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. GH Review: review-needed labels Mar 29, 2017
@janicduplessis
Copy link
Contributor

janicduplessis commented Apr 4, 2017

How can I update the documentation and remove the "ios" badge on the letterSpacing option?

You can just remove the @ios annotation here https://github.com/facebook/react-native/blob/master/Libraries/Text/TextStylePropTypes.js#L52

@janicduplessis
Copy link
Contributor

Also maybe we should specify in the doc that it only works on android 5+

@jerolimov
Copy link
Contributor Author

Thanks @janicduplessis for the hint. I removed the badge, added some documentation and rebased the branch.

@kesha-antonov
Copy link
Contributor

+1 need this!

@jerolimov
Copy link
Contributor Author

jerolimov commented Apr 26, 2017

Sorry for the spam, but after 4w any feedback would be great. So after watching the git annotation of the changed files I decided to ping you.. 😏

/cc @janicduplessis @mkonicek @emilsjolander @astreet

Latest push just rebased this PR again on master.

@janicduplessis
Copy link
Contributor

Sorry for the delay we are a bit swamped in PRs as you can see. Feel free to ping us if we forget to check back.

It looks good to me but would like a second review from someone at FB that is more familiar with that code since it will affect apps quite a lot. @AaaChiuuu could you have a look?

Copy link
Contributor

@astreet astreet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff looks really good, thanks! I'm concerned about letter spacing working slightly differently on the two platforms though, even with the work-around (the workaround also doesn't work if the text is inline). Can you think of other options? Can we at least automatically apply the negative margin by translating the text by half the increased letter spacing?

private final float mLetterSpacing;

public CustomLetterSpacingSpan(float letterSpacing) {
Assertions.assertCondition(!Float.isNaN(letterSpacing) && letterSpacing != 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use SoftAssertions so that we throw a catchable Exception and not an Error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that this happen only if you change the internal code. This can not happen by any input from JSX. But I can change this when nothing other blocks this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still would like us to not use Errors when we can use Exceptions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Will change it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having less points to discuss is the fastest way to get PR approved. 😄

@jerolimov
Copy link
Contributor Author

jerolimov commented May 2, 2017

I have thought about different solutions and also tried to implement such a "negative" margin. But it doesn't work and make other thinks must more complex. I think this is a good-for-now-but-not-perfect solution. Its up to the developers to apply different letterspacing inline and test them on both platforms.

For us (and I hope for many other developers) this should work fine in headline and in 90% of the letterspacing cases with multiline text. I'm sorry I see currently no option that I can improve these.

Copy link
Contributor

@astreet astreet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just looked through the Span/Paint APIs and I think matching iOS behavior is too advanced for what they let us do :(

private final float mLetterSpacing;

public CustomLetterSpacingSpan(float letterSpacing) {
Assertions.assertCondition(!Float.isNaN(letterSpacing) && letterSpacing != 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still would like us to not use Errors when we can use Exceptions

* is calculated based on your font size and the font family. To left-align a text similar
* to iOS (or in different font sizes) you should add a Platform-specific negative layout attribute.
*
* iOS: The additional space will be added behind the character and is defined in points.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this implying that android and ios also use two different units? If so, can we make them use the same unit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that are different units. The problem is that the Android only supports the M-unit while iOS only supports points. Is it not possible (for me) to use the exakt same unit here. 🤷‍♂️

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see two options then:

  1. convert em to pt: unfortunately this is going to require measuring the width of an M in the current font/font size (and also recalculating it when the font/font size changes), and it would probably work quite poorly for any animations that adjust font size (not that I know of any).

  2. Create two different props (letterSpacingIOS, letterSpacingAndroid).

I much prefer (1) but let me know what you think. I don't think having the same prop behave very differently on both platforms is a good solution.

Copy link
Contributor Author

@jerolimov jerolimov May 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like you, I would prefer option one.

Can you help me to calculating the exact width of the letter M in a performant way?

Did you see my current calculation in calculateLetterSpacing which is a "high performant" 😏 way which calculates a good result in 90%... 🤷‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, when defining 5 as letter spacing, this means 5 points on iOS.

With the current implementation this means "letterSpacingInput / fontSize * 2f" M on Android.

With a fontSize of 14 dpi this means ~0.71 M. And because the "small M" needs round about 8-10 dpi* from left to right this results in 5-6 dpis "real letter spacing" on Android.

With a fontSize of 28 dpi this means ~0.36 M. And because the "bigger M" here needs round about 16-20 dpi* from left to right this results in 6-7 dpis "real letter spacing" on Android.

In our case (and I think in many more cases) this is much better than no letter spacing. 🙈 Also if I know, an addtional PR can improve this in the future. And I'm looking forward to anybody who can and will do this. S/he will get some free 🍻 from us, here in Cologne. 😄

*I does not measure the size exactly because it depends on the selected font family.

Copy link
Contributor

@astreet astreet May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'm fine siding with practicality here then. If you wanted to measure an 'M', you'd want to look at how we do it in our text shadow node: basically use a BoringLayout. But I'm also fine if you come up with some formula that at least factors in font size (looks like you already have something like that -- if so, add some more detailed docs for the prop about how we're emulating what iOS does, but it isn't perfect)

@Hunter-Dolan
Copy link

Can someone please get this merged? Letter spacing is a very big deal to many design conscious clients/designers. I would fix the merge conflict if I had authorization to.

@sesm
Copy link

sesm commented Jul 6, 2017

@jerolimov @astreet
Guys, what can community do to help you get this PR merged?
What is the primary PR for this issue now, this one or #13877?

@hubciorz
Copy link

hubciorz commented Aug 3, 2017

@jerolimov @astreet
Can we do something to help you merge that? Do you need more tests or POCs?

I agree with @Hunter-Dolan that this is a really really really big deal.

@facebook-github-bot
Copy link
Contributor

@jerolimov I tried to find reviewers for this pull request and wanted to ping them to take another look. However, based on the blame information for the files in this pull request I couldn't find any reviewers. This sometimes happens when the files in the pull request are new or don't exist on master anymore. Is this pull request still relevant? If yes could you please rebase? In case you know who has context on this code feel free to mention them in a comment (one person is fine). Thanks for reading and hope you will continue contributing to the project.

@RWOverdijk
Copy link

Bump.

Because Android TextView#setLetterSpacing expects the letter spacing
value in 'EM' unit, where one is defined by the width of the letter 'M'.
Typical values for slight expansion will be around 0.05. Negative values
will tighten text. So we use NaN as not defined value.

This method calculates an 'EM' *approach* based on the input and the
calculated font size. With common fonts this calculated value renders a
similar spacing and layout to iOS.
@pull-bot
Copy link

Attention: @shergin

Generated by 🚫 dangerJS

jerolimov added a commit to jerolimov/react-native-letterspacing-example that referenced this pull request Aug 26, 2017
@jerolimov
Copy link
Contributor Author

I tested #13877 which doesn't work for me after rebasing it. For both branches I created a small test project:

I could take the idea from the responses above and PR 13877 to calculate the correct "M" value.

But I still have the issue that Android split the additional letter spacing and add this space on the left and on the right of each character, where iOS add this only on the right side. Adding a negative padding (left and right) on Android (in ReactTextView#setText(ReactTextUpdate) doesn't work yet.

@shergin
Copy link
Contributor

shergin commented Aug 29, 2017

@jerolimov Could you please add a small example to RNTester app?

@facebook-github-bot
Copy link
Contributor

@jerolimov I tried to find reviewers for this pull request and wanted to ping them to take another look. However, based on the blame information for the files in this pull request I couldn't find any reviewers. This sometimes happens when the files in the pull request are new or don't exist on master anymore. Is this pull request still relevant? If yes could you please rebase? In case you know who has context on this code feel free to mention them in a comment (one person is fine). Thanks for reading and hope you will continue contributing to the project.

@malashkevich
Copy link

@jerolimov @shergin What we can do in order to continue work on this?
There is already 49 version of RN but still no letter spacing in Android.

@shergin
Copy link
Contributor

shergin commented Oct 20, 2017

@jerolimov Could you please resolve conflicts?

@shergin
Copy link
Contributor

shergin commented Oct 20, 2017

@jerolimov How is this solution different from #13199? How do you think, which is better?

@dickie81
Copy link

dickie81 commented Nov 3, 2017

@jerolimov I've resolved the conflicts if it helps get things moving. Really looking forward to this landing.
https://github.com/jerolimov/react-native/pull/1

@dickie81
Copy link

dickie81 commented Nov 8, 2017

@astreet @shergin @jerolimov: We seem to be at an impasse here. Should I raise a new PR directly against facebook/react-native ?

@yenda
Copy link

yenda commented Nov 9, 2017

@dickie81 thanks for working on this, if it can get things to move forward please do !

@motiz88
Copy link
Contributor

motiz88 commented Dec 30, 2017

I'd like to add my two cents here following #16801 (review) and #13877 (comment) in the hopes of getting this feature back on track. The usual disclaimer applies - I'm not a RN contributor (yet) or maintainer, just an interested user who has tinkered with letter spacing before.

  • I believe CustomLetterSpacingSpan, as used here, is the most viable approach (as outlined in Add letter spacing for Android versions >= Lollipop (5.0). #13877 (comment)) for rendering letter spacing consistently with the rest of the RN Text implementation. Hence I think this PR is the most viable out of the three that are currently open.
  • I vote for accepting (and documenting, as has been done here) the divergent rendering of letterSpacing on Android vs iOS, as there seems to be no universal solution in terms of layout, and the only real alternative would be to plug in a different text shaping algorithm to override Android's - a massive undertaking which I believe is not in scope here. (This would be a valid direction for RN to take for greater cross-platform compatibility, but I digress.)
  • The only real blocker here, IMHO, is the unit conversion logic, but I believe this is entirely solvable as outlined in Add letter spacing for Android versions >= Lollipop (5.0). #13877 (comment). (Reading the actual fontSize in CustomLetterSpacingSpan, converting to SP/DIP appropriately and dividing the letter spacing by that size should yield the correct value in ems)

I will have a stab at resolving conflicts with master and addressing the above points. I would love some signal from a RN maintainer (@astreet @shergin ?) that this has a chance of getting merged (esp. without me updating/testing the corresponding Flat UI implementation, which I gather is in a WIP/semi-broken state?)

@motiz88
Copy link
Contributor

motiz88 commented Feb 20, 2018

@jerolimov Want to close this to keep the focus on #17398?

facebook-github-bot pushed a commit that referenced this pull request Feb 27, 2018
Summary:
`letterSpacing` is completely missing from RN Android at the moment.

I've reviewed the `letterSpacing` implementations in #13199, #13877 and #16801 (that all seem to have stalled) and managed to put together an improved one based on #13199, updated to merge cleanly post 6114f86, that resolves the [issues](#13199 (comment)) I've identified with that code.

I believe this is the closest PR yet to a correct implementation of this feature, with a few caveats:

- As with the other PRs, this only works on Android >= 5.0 (silently falling back to no letter spacing on older versions). Is this acceptable for a RN feature, in general? Would a dev mode warning be desirable?
- The other PRs seem to have explored the space of potential solutions to the layout issue ([Android renders space _around_ glyphs](https://issuetracker.google.com/issues/37079859), iOS to the _right_ of each one) and come up empty, so I've opted to merely document the difference.
- I have neither updated nor tested the "Flat" UI implementation - everything compiles but I've taken [this comment](#12770 (comment)) to mean there's no point in trying to wade through it on my own right now; I'm happy to tackle it if given some pointers.
- The implementation in `ReactEditText` is only there to handle the placeholder text, as `ReactBaseTextShadowNode` already affects the input control's contents correctly.
  - I'm not sure whether `<TextInput>` is meant to respect `allowFontScaling`; I've taken my cue here from `ReactTextInputManager.setFontSize()`, and used the same units (SP) to interpret the value in `ReactEditText.setLetterSpacingPt()`.
  - I'm not sure whether `<TextInput>` is even meant to support `letterSpacing` - it doesn't actually work on iOS. I'm not going to be able to handle the Objective-C side of this, not as part of this PR at least.
- I have not added unit tests to `ReactTextTest` - is this desirable? I see that some other props such as `lineHeight` aren't covered there (unless I'm not looking in the right place).
- Overall, I'm new to this codebase, so it's likely I've missed something not mentioned here.

Note comment re: unit tests above; RNTester screenshots follow.

| iOS (existing functionality, amended test) | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458459-c8d59498-edcb-11e7-8c8f-e7426f723886.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458473-2a1ca368-edcc-11e7-9ce6-30c6d3a48660.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458481-6c60a36e-edcc-11e7-9af5-9734dd722ced.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458486-8b3cdcf8-edcc-11e7-974b-25c6085fa674.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458492-d69a77be-edcc-11e7-896f-21212621dbee.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458490-b3a1139e-edcc-11e7-88c8-79d4430d1514.png width=300> |

facebook/react-native-website#105 - this docs PR is edited slightly from what's in `TextStylePropTypes` here; happy to align either one to the other after a review.

[ANDROID] [FEATURE] [Text] - Implemented letterSpacing
Closes #17398

Reviewed By: mdvacca

Differential Revision: D6837718

Pulled By: hramos

fbshipit-source-id: 5c9d49e9cf4af6457b636416ce5fe15315aab72c
vincentriemer pushed a commit to vincentriemer/react-native-dom that referenced this pull request Mar 6, 2018
Summary:
`letterSpacing` is completely missing from RN Android at the moment.

I've reviewed the `letterSpacing` implementations in #13199, #13877 and #16801 (that all seem to have stalled) and managed to put together an improved one based on #13199, updated to merge cleanly post facebook/react-native@6114f86, that resolves the [issues](facebook/react-native#13199 (comment)) I've identified with that code.

I believe this is the closest PR yet to a correct implementation of this feature, with a few caveats:

- As with the other PRs, this only works on Android >= 5.0 (silently falling back to no letter spacing on older versions). Is this acceptable for a RN feature, in general? Would a dev mode warning be desirable?
- The other PRs seem to have explored the space of potential solutions to the layout issue ([Android renders space _around_ glyphs](https://issuetracker.google.com/issues/37079859), iOS to the _right_ of each one) and come up empty, so I've opted to merely document the difference.
- I have neither updated nor tested the "Flat" UI implementation - everything compiles but I've taken [this comment](facebook/react-native#12770 (comment)) to mean there's no point in trying to wade through it on my own right now; I'm happy to tackle it if given some pointers.
- The implementation in `ReactEditText` is only there to handle the placeholder text, as `ReactBaseTextShadowNode` already affects the input control's contents correctly.
  - I'm not sure whether `<TextInput>` is meant to respect `allowFontScaling`; I've taken my cue here from `ReactTextInputManager.setFontSize()`, and used the same units (SP) to interpret the value in `ReactEditText.setLetterSpacingPt()`.
  - I'm not sure whether `<TextInput>` is even meant to support `letterSpacing` - it doesn't actually work on iOS. I'm not going to be able to handle the Objective-C side of this, not as part of this PR at least.
- I have not added unit tests to `ReactTextTest` - is this desirable? I see that some other props such as `lineHeight` aren't covered there (unless I'm not looking in the right place).
- Overall, I'm new to this codebase, so it's likely I've missed something not mentioned here.

Note comment re: unit tests above; RNTester screenshots follow.

| iOS (existing functionality, amended test) | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458459-c8d59498-edcb-11e7-8c8f-e7426f723886.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458473-2a1ca368-edcc-11e7-9ce6-30c6d3a48660.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458481-6c60a36e-edcc-11e7-9af5-9734dd722ced.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458486-8b3cdcf8-edcc-11e7-974b-25c6085fa674.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458492-d69a77be-edcc-11e7-896f-21212621dbee.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458490-b3a1139e-edcc-11e7-88c8-79d4430d1514.png width=300> |

facebook/react-native-website#105 - this docs PR is edited slightly from what's in `TextStylePropTypes` here; happy to align either one to the other after a review.

[ANDROID] [FEATURE] [Text] - Implemented letterSpacing
Closes facebook/react-native#17398

Reviewed By: mdvacca

Differential Revision: D6837718

Pulled By: hramos

fbshipit-source-id: 5c9d49e9cf4af6457b636416ce5fe15315aab72c
cpirich pushed a commit to tracemeinc/react-native that referenced this pull request Mar 16, 2018
Summary:
`letterSpacing` is completely missing from RN Android at the moment.

I've reviewed the `letterSpacing` implementations in facebook#13199, facebook#13877 and facebook#16801 (that all seem to have stalled) and managed to put together an improved one based on facebook#13199, updated to merge cleanly post facebook@6114f86, that resolves the [issues](facebook#13199 (comment)) I've identified with that code.

I believe this is the closest PR yet to a correct implementation of this feature, with a few caveats:

- As with the other PRs, this only works on Android >= 5.0 (silently falling back to no letter spacing on older versions). Is this acceptable for a RN feature, in general? Would a dev mode warning be desirable?
- The other PRs seem to have explored the space of potential solutions to the layout issue ([Android renders space _around_ glyphs](https://issuetracker.google.com/issues/37079859), iOS to the _right_ of each one) and come up empty, so I've opted to merely document the difference.
- I have neither updated nor tested the "Flat" UI implementation - everything compiles but I've taken [this comment](facebook#12770 (comment)) to mean there's no point in trying to wade through it on my own right now; I'm happy to tackle it if given some pointers.
- The implementation in `ReactEditText` is only there to handle the placeholder text, as `ReactBaseTextShadowNode` already affects the input control's contents correctly.
  - I'm not sure whether `<TextInput>` is meant to respect `allowFontScaling`; I've taken my cue here from `ReactTextInputManager.setFontSize()`, and used the same units (SP) to interpret the value in `ReactEditText.setLetterSpacingPt()`.
  - I'm not sure whether `<TextInput>` is even meant to support `letterSpacing` - it doesn't actually work on iOS. I'm not going to be able to handle the Objective-C side of this, not as part of this PR at least.
- I have not added unit tests to `ReactTextTest` - is this desirable? I see that some other props such as `lineHeight` aren't covered there (unless I'm not looking in the right place).
- Overall, I'm new to this codebase, so it's likely I've missed something not mentioned here.

Note comment re: unit tests above; RNTester screenshots follow.

| iOS (existing functionality, amended test) | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458459-c8d59498-edcb-11e7-8c8f-e7426f723886.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458473-2a1ca368-edcc-11e7-9ce6-30c6d3a48660.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458481-6c60a36e-edcc-11e7-9af5-9734dd722ced.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458486-8b3cdcf8-edcc-11e7-974b-25c6085fa674.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458492-d69a77be-edcc-11e7-896f-21212621dbee.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458490-b3a1139e-edcc-11e7-88c8-79d4430d1514.png width=300> |

facebook/react-native-website#105 - this docs PR is edited slightly from what's in `TextStylePropTypes` here; happy to align either one to the other after a review.

[ANDROID] [FEATURE] [Text] - Implemented letterSpacing
Closes facebook#17398

Reviewed By: mdvacca

Differential Revision: D6837718

Pulled By: hramos

fbshipit-source-id: 5c9d49e9cf4af6457b636416ce5fe15315aab72c
@react-native-bot react-native-bot added Missing Changelog This PR appears to be missing a changelog, or they are incorrectly formatted. Ran Commands One of our bots successfully processed a command. Android labels Mar 16, 2018
@react-native-bot react-native-bot added Platform: Android Android applications. Ran Commands One of our bots successfully processed a command. labels Mar 18, 2018
guyca pushed a commit to wix-playground/react-native that referenced this pull request Mar 29, 2018
Summary:
`letterSpacing` is completely missing from RN Android at the moment.

I've reviewed the `letterSpacing` implementations in facebook#13199, facebook#13877 and facebook#16801 (that all seem to have stalled) and managed to put together an improved one based on facebook#13199, updated to merge cleanly post facebook@6114f86, that resolves the [issues](facebook#13199 (comment)) I've identified with that code.

I believe this is the closest PR yet to a correct implementation of this feature, with a few caveats:

- As with the other PRs, this only works on Android >= 5.0 (silently falling back to no letter spacing on older versions). Is this acceptable for a RN feature, in general? Would a dev mode warning be desirable?
- The other PRs seem to have explored the space of potential solutions to the layout issue ([Android renders space _around_ glyphs](https://issuetracker.google.com/issues/37079859), iOS to the _right_ of each one) and come up empty, so I've opted to merely document the difference.
- I have neither updated nor tested the "Flat" UI implementation - everything compiles but I've taken [this comment](facebook#12770 (comment)) to mean there's no point in trying to wade through it on my own right now; I'm happy to tackle it if given some pointers.
- The implementation in `ReactEditText` is only there to handle the placeholder text, as `ReactBaseTextShadowNode` already affects the input control's contents correctly.
  - I'm not sure whether `<TextInput>` is meant to respect `allowFontScaling`; I've taken my cue here from `ReactTextInputManager.setFontSize()`, and used the same units (SP) to interpret the value in `ReactEditText.setLetterSpacingPt()`.
  - I'm not sure whether `<TextInput>` is even meant to support `letterSpacing` - it doesn't actually work on iOS. I'm not going to be able to handle the Objective-C side of this, not as part of this PR at least.
- I have not added unit tests to `ReactTextTest` - is this desirable? I see that some other props such as `lineHeight` aren't covered there (unless I'm not looking in the right place).
- Overall, I'm new to this codebase, so it's likely I've missed something not mentioned here.

Note comment re: unit tests above; RNTester screenshots follow.

| iOS (existing functionality, amended test) | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458459-c8d59498-edcb-11e7-8c8f-e7426f723886.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458473-2a1ca368-edcc-11e7-9ce6-30c6d3a48660.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458481-6c60a36e-edcc-11e7-9af5-9734dd722ced.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458486-8b3cdcf8-edcc-11e7-974b-25c6085fa674.png width=300> |

| iOS _(not implemented, test not in this branch)_ | Android (new functionality & test) |
| - | - |
| <img src=https://user-images.githubusercontent.com/2246565/34458492-d69a77be-edcc-11e7-896f-21212621dbee.png width=300> | <img src=https://user-images.githubusercontent.com/2246565/34458490-b3a1139e-edcc-11e7-88c8-79d4430d1514.png width=300> |

facebook/react-native-website#105 - this docs PR is edited slightly from what's in `TextStylePropTypes` here; happy to align either one to the other after a review.

[ANDROID] [FEATURE] [Text] - Implemented letterSpacing
Closes facebook#17398

Reviewed By: mdvacca

Differential Revision: D6837718

Pulled By: hramos

fbshipit-source-id: 5c9d49e9cf4af6457b636416ce5fe15315aab72c
@jerolimov jerolimov closed this May 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Missing Changelog This PR appears to be missing a changelog, or they are incorrectly formatted. Platform: Android Android applications. Ran Commands One of our bots successfully processed a command.
Projects
None yet
Development

Successfully merging this pull request may close these issues.