Summary:
This diff implement the CSS z-index for React Native iOS views. We've had numerous pull request for this feature, but they've all attempted to use the `layer.zPosition` property, which is problematic for two reasons:
1. zPosition only affects rendering order, not event processing order. Views with a higher zPosition will appear in front of others in the hierarchy, but won't be the first to receive touch events, and may be blocked by views that are visually behind them.
2. when using a perspective transform matrix, views with a nonzero zPosition will be rendered in a different position due to parallax, which probably isn't desirable.
See https://github.com/facebook/react-native/pull/7825 for further discussion of this problem.
So instead of using `layer.zPosition`, I've implemented this by actually adjusting the order of the subviews within their parent based on the zIndex. This can't be done on the JS side because it would affect layout, which is order-dependent, so I'm doing it inside the view itself.
It works as follows:
1. The `reactSubviews` array is set, whose order matches the order of the JS components and shadowView components, as specified by the UIManager.
2. `didUpdateReactSubviews` is called, which in turn calls `sortedSubviews` (which lazily generates a sorted array of `reactSubviews` by zIndex) and inserts the result into the view.
3. If a subview is added or removed, or the zIndex of any subview is changed, the previous `sortedSubviews` array is cleared and `didUpdateReactSubviews` is called again.
To demonstrate it working, I've modified the UIExplorer example from https://github.com/facebook/react-native/pull/7825
Reviewed By: javache
Differential Revision: D3365717
fbshipit-source-id: b34aa8bfad577bce023f8af5414f9b974aafd8aa
Summary:
This diff refactors the view update process into two stages:
1. The `reactSubviews` array is set, whose order matches the order of the JS components and shadowView components, as specified by the UIManager.
2. The `didUpdateReactSubviews` method is called, which actually inserts the reactSubviews into the view hierarchy.
This simplifies a lot of the hacks we had for special-case treatment of subviews: In many cases we don't want to actually insert `reactSubviews` into the parentView, and we had a bunch of component-specific solutions for that (typically overriding all of the reactSubviews methods to store views in an array). Now, we can simply override the `didUpdateReactSubviews` method for those views to do nothing, or do something different.
Reviewed By: wwjholmes
Differential Revision: D3396594
fbshipit-source-id: 92fc56fd31db0cfc66aac3d1634a4d4ae3903085
Summary:
The `removeClippedSubviews` feature works by umounting views from the hierarchy if they move outside the bounds of their parent.
This was previously restricted to clipping views which had `overflow: hidden`, since we cannot efficiently check whether the subviews of a view go outside its bounds, and so clipping a view that has potentially overflowing children becomes an expensive recursive operation.
The problem with this is that `overflow: visible` is the default, and it's not well documented nor easy to tell that `removeClippedSubviews` has been set up correctly (i.e. with all children having `overflow: hidden`).
When I checked, I found that `removeClippedSubviews` was not working on any of the examples in UIExplorer, nor in several of our internal apps, because the views inside the ListView has `overflow: visible`. This was probably caused by an infra change at some point, but I'm not sure how long it's been broken.
It's vanishingly unlikely that anyone would ever deliberately want subviews to overflow their bounds in this scenario, so I've updated the logic to simply ignore the `overflow` property and assume that views should be clipped if you are using the `removeClippedSubviews` property on the parent.
Cons / Breaking changes: in some rare circumstances, a view might get clipped prematurely if its parent is outside the scrollview bounds, but it itself is inside. This doesn't occur in practice in any of our products, and could be worked around with additional wrapper views if it did.
Pros: removeClippedSubviews is now much easier to use, and much more likely to work as intended, so most list-based apps should see a performance improvement.
Reviewed By: javache
Differential Revision: D3385316
fbshipit-source-id: 1c0064a4c21340a971ba80d794062a356ae6cfb3
Summary:
Previously we had an issue where we would clip visible views during an animation, like swiping back a VC.
The root cause was mismatch between a view's frame and what is visible on screen. This happens because during an animation the frame (and other properties) of the animated view has final values, even that it's not yet rendered at that position.
This diff fixes this issue by not looking for a clippingView above the react root view, since the animation for VC transitions happens at view higher above the root view.
Reviewed By: javache
Differential Revision: D3281655
fbshipit-source-id: 996b1a9f223c5b2274dd3d7c05b8936612af05ba
Summary:New prop `hitSlop` allows extending the touch area of Touchable components. This makes it easier to touch small buttons without needing to change your styles.
It takes `top`, `bottom`, `left`, and `right` same as the `pressRetentionOffset` prop. When a touch is moved, `hitSlop` is combined with `pressRetentionOffset` to determine how far the touch can move off the button before deactivating the button.
On Android I had to add a new file `ids.xml` to generate a unique ID to use for the tag where I store the `hitSlop` state. The iOS side is more straightforward.
terribleben worked on the iOS and JS parts of this diff.
Fixes#110
Closes https://github.com/facebook/react-native/pull/5720
Differential Revision: D2941671
Pulled By: androidtrunkagent
fb-gh-sync-id: 07e3eb8b6a36eebf76968fdaac3c6ac335603194
shipit-source-id: 07e3eb8b6a36eebf76968fdaac3c6ac335603194
Summary:
public
React Native currently exposes the iOS layer shadow properties more-or-less directly, however there are a number of problems with this:
1) Performance when using these properties is poor by default. That's because iOS calculates the shadow by getting the exact pixel mask of the view, including any tranlucent content, and all of its subviews, which is very CPU and GPU-intensive.
2) The iOS shadow properties do not match the syntax or semantics of the CSS box-shadow standard, and are unlikely to be possible to implement on Android.
3) We don't expose the `layer.shadowPath` property, which is crucial to getting good performance out of layer shadows.
This diff solves problem number 1) by implementing a default `shadowPath` that matches the view border for views with an opaque background. This improves the performance of shadows by optimizing for the common usage case. I've also reinstated background color propagation for views which have shadow props - this should help ensure that this best-case scenario occurs more often.
For views with an explicit transparent background, the shadow will continue to work as it did before ( `shadowPath` will be left unset, and the shadow will be derived exactly from the pixels of the view and its subviews). This is the worst-case path for performance, however, so you should avoid it unless absolutely necessary. **Support for this may be disabled by default in future, or dropped altogether.**
For translucent images, it is suggested that you bake the shadow into the image itself, or use another mechanism to pre-generate the shadow. For text shadows, you should use the textShadow properties, which work cross-platform and have much better performance.
Problem number 2) will be solved in a future diff, possibly by renaming the iOS shadowXXX properties to boxShadowXXX, and changing the syntax and semantics to match the CSS standards.
Problem number 3) is now mostly moot, since we generate the shadowPath automatically. In future, we may provide an iOS-specific prop to set the path explicitly if there's a demand for more precise control of the shadow.
Reviewed By: weicool
Differential Revision: D2827581
fb-gh-sync-id: 853aa018e1d61d5f88304c6fc1b78f9d7e739804
Summary:
public
The fix for border smearing introduced a bug where borders + background would sometimes not be rendered if the view was created at a small size (e.g. zero) and then resized.
This diff fixes that by redrawing the border if the view size changes. There is some opportunity to optimize this in future by performing some logic up-front to detect if the redrawing is necessary, but I thought I'd keep it simple for this bug fix rather than risk introducing further bugs.
Reviewed By: jingc
Differential Revision: D2817365
fb-gh-sync-id: eca164e8ce03a66598677c9e05496791230b5210
Summary:
public
The iOS border rendering code did not follow the CSS spec in cases where the sum of adjacent border radii was greater than the width of the view, resulting in drawing glitches such as pixel smear and borders appearing stretched or squashed.
This diff brings our implementation closer to spec-compliance in these cases. I also fixed a longstanding issue with ghostly diagonal lines appearing at the corners due to antialiasing rounding errors!
Fixes
https://github.com/facebook/react-native/issues/1572https://github.com/facebook/react-native/issues/2089https://github.com/facebook/react-native/issues/4604
Reviewed By: tadeuzagallo
Differential Revision: D2811249
fb-gh-sync-id: c3dd2721e0a01a432fa4dc78daa05680595edd08
Summary:
Support dashed and dotted border styles on iOS
public
Reviewed By: nicklockwood
Differential Revision: D2773579
fb-gh-sync-id: f4b99943f38e849602295a86bdb1780c0abbc8e8
Summary: public
Added lightweight genarics annotations to make the code more readable and help the compiler catch bugs.
Fixed some type bugs and improved bridge validation in a few places.
Reviewed By: javache
Differential Revision: D2600189
fb-gh-sync-id: f81e22f2cdc107bf8d0b15deec6d5b83aacc5b56
Summary: This addresses #3577 and #3533. It adds the ability to test for subview.clipsToBounds.
Closes https://github.com/facebook/react-native/pull/3750
Reviewed By: svcscm
Differential Revision: D2592878
Pulled By: nicklockwood
fb-gh-sync-id: a87842b87dc0b455120e6007059b5d9a51a53ea2
Summary:
Currently, the system for mapping JS event handlers to blocks is quite clean on the JS side, but is clunky on the native side. The event property is passed as a boolean, which can then be checked by the native side, and if true, the native side is supposed to send an event via the event dispatcher.
This diff adds the facility to declare the property as a block instead. This means that the event side can simply call the block, and it will automatically send the event. Because the blocks for bubbling and direct events are named differently, we can also use this to generate the event registration data and get rid of the arrays of event names.
The name of the event is inferred from the property name, which means that the property for an event called "load" must be called `onLoad` or the mapping won't work. This can be optionally remapped to a different property name on the view itself if necessary, e.g.
RCT_REMAP_VIEW_PROPERTY(onLoad, loadEventBlock, RCTDirectEventBlock)
If you don't want to use this mechanism then for now it is still possible to declare the property as a BOOL instead and use the old mechanism (this approach is now deprecated however, and may eventually be removed altogether).
Summary:
RCTCache had really bad insertion performance when the cache was full due to having to LRU-sort the entries. This was making color
animations very slow.
I've fixed this in two ways:
1) by removing the sort and doing a linear search to remove old entries, which changes insertion perf to O(n) in the worst case instead of O(n log n) or even (n2).
2) by reducing the size of the color cache to 128 from 1024, which should be fine for normal use, without penalising animation performance.
Separately, border colors were not being retained, which caused crashes when the color cache was cleared. I've fixed that by retaining the border colors inside RCTView.
Summary:
@public
I've increased the warning levels in the OSS frameworks, which caught a bunch of minor issues. I also fixed some new errors in Xcode 7 relating to designated initializers and TLS security.
Test Plan:
* Test the sample apps and make sure they still work.
* Run tests.
Summary:
- Returns matching subview hitTest or super hitTest if no match found. Should fix#99 .
Closes https://github.com/facebook/react-native/pull/501
Github Author: Boopathi Rajaa <me@boopathi.in>
Test Plan: Imported from GitHub, without a `Test Plan:` line.