diff --git a/docs/Accessibility.md b/docs/Accessibility.md index 9ff6e18..6e8dfe3 100644 --- a/docs/Accessibility.md +++ b/docs/Accessibility.md @@ -1,14 +1,10 @@ --- id: accessibility title: Accessibility -layout: docs -category: Guides -permalink: docs/accessibility.html -next: timers -previous: animations --- ## Native App Accessibility (iOS and Android) + Both iOS and Android provide APIs for making apps accessible to people with disabilities. In addition, both platforms provide bundled assistive technologies, like the screen readers VoiceOver (iOS) and TalkBack (Android) for the visually impaired. Similarly, in React Native we have included APIs designed to provide developers with support for making apps more accessible. Take note, iOS and Android differ slightly in their approaches, and thus the React Native implementations may vary by platform. In addition to this documentation, you might find [this blog post](https://code.facebook.com/posts/435862739941212/making-react-native-apps-accessible/) about React Native accessibility to be useful. @@ -21,7 +17,7 @@ In addition to this documentation, you might find [this blog post](https://code. When `true`, indicates that the view is an accessibility element. When a view is an accessibility element, it groups its children into a single selectable component. By default, all touchable elements are accessible. -On Android, ‘accessible={true}’ property for a react-native View will be translated into native ‘focusable={true}’. +On Android, `accessible={true}` property for a react-native View will be translated into native `focusable={true}`. ```javascript @@ -32,16 +28,17 @@ On Android, ‘accessible={true}’ property for a react-native View will be tra In the above example, we can't get accessibility focus separately on 'text one' and 'text two'. Instead we get focus on a parent view with 'accessible' property. - - #### accessibilityLabel (iOS, Android) When a view is marked as accessible, it is a good practice to set an accessibilityLabel on the view, so that people who use VoiceOver know what element they have selected. VoiceOver will read this string when a user selects the associated element. -To use, set the `accessibilityLabel` property to a custom string on your View: +To use, set the `accessibilityLabel` property to a custom string on your View, Text or Touchable: ```javascript - + Press me! @@ -50,8 +47,65 @@ To use, set the `accessibilityLabel` property to a custom string on your View: In the above example, the `accessibilityLabel` on the TouchableOpacity element would default to "Press me!". The label is constructed by concatenating all Text node children separated by spaces. +#### accessibilityHint (iOS, Android) + +An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not obvious from the accessibility label. + +To use, set the `accessibilityHint` property to a custom string on your View, Text or Touchable: + +```javascript + + + Back + + +``` + +iOS In the above example, VoiceOver will read the hint after the label, if the user has hints enabled in the device's VoiceOver settings. Read more about guidelines for accessibilityHint in the [iOS Developer Docs](https://developer.apple.com/documentation/objectivec/nsobject/1615093-accessibilityhint) + +Android In the above example, Talkback will read the hint after the label. At this time, hints cannot be turned off on Android. + +#### accessibilityIgnoresInvertColors(iOS) + +Inverting screen colors is an Accessibility feature that makes the iPhone and iPad easier on the eyes for some people with a sensitivity to brightness, easier to distinguish for some people with color blindness, and easier to make out for some people with low vision. However, sometimes you have views such as photos that you don't want to be inverted. In this case, you can set this property to be false so that these specific views won't have their colors inverted. + +#### accessibilityRole (iOS, Android) + +> **Note:** Accessibility Role and Accessibility States are meant to be a cross-platform solution to replace `accessibilityTraits` and `accessibilityComponentType`, which will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. + +Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on Android the type of element that is focused on. To use, set the `accessibilityRole` property to one of the following strings: + +* **none** Used when the element has no role. +* **button** Used when the element should be treated as a button. +* **link** Used when the element should be treated as a link. +* **search** Used when the text field element should also be treated as a search field. +* **image** Used when the element should be treated as an image. Can be combined with button or link, for example. +* **keyboardkey** Used when the element acts as a keyboard key. +* **text** Used when the element should be treated as static text that cannot change. +* **adjustable** Used when an element can be "adjusted" (e.g. a slider). +* **imagebutton** Used when the element should be treated as a button and is also an image. +* **header** Used when an element acts as a header for a content section (e.g. the title of a navigation bar). +* **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. + +#### accessibilityStates (iOS, Android) + +> **Note:** > `accessibilityRole` and `accessibilityStates` are meant to be a cross-platform solution to replace `accessibilityTraits` and `accessibilityComponentType`, which will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. + +Accessibility State tells a person using either VoiceOver on iOS or TalkBack on Android the state of the element currently focused on. The state of the element can be set either to `selected` or `disabled` or both: + +* **selected** Used when the element is in a selected state. For example, a button is selected. +* **disabled** Used when the element is disabled and cannot be interacted with. + +To use, set the `accessibilityStates` to an array containing either `selected`, `disabled`, or both. + #### accessibilityTraits (iOS) +> **Note:** `accessibilityTraits` will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. + Accessibility traits tell a person using VoiceOver what kind of element they have selected. Is this element a label? A button? A header? These questions are answered by `accessibilityTraits`. To use, set the `accessibilityTraits` property to one of (or an array of) accessibility trait strings: @@ -62,11 +116,11 @@ To use, set the `accessibilityTraits` property to one of (or an array of) access * **header** Used when an element acts as a header for a content section (e.g. the title of a navigation bar). * **search** Used when the text field element should also be treated as a search field. * **image** Used when the element should be treated as an image. Can be combined with button or link, for example. -* **selected** Used when the element is selected. For example, a selected row in a table or a selected button within a segmented control. +* **selected** Used when the element is selected. For example, a selected row in a table or a selected button within a segmented control. * **plays** Used when the element plays its own sound when activated. * **key** Used when the element acts as a keyboard key. * **text** Used when the element should be treated as static text that cannot change. -* **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. For example, when Weather first launches, the element with today's weather conditions is marked with this trait. +* **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. For example, when Weather first launches, the element with today's weather conditions is marked with this trait. * **disabled** Used when the control is not enabled and does not respond to user input. * **frequentUpdates** Used when the element frequently updates its label or value, but too often to send notifications. Allows an accessibility client to poll for changes. A stopwatch would be an example. * **startsMedia** Used when activating an element starts a media session (e.g. playing a movie, recording audio) that should not be interrupted by output from an assistive technology, like VoiceOver. @@ -78,8 +132,13 @@ To use, set the `accessibilityTraits` property to one of (or an array of) access A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver. -For example, in a window that contains sibling views `A` and `B`, setting `accessibilityViewIsModal` to `true` on view `B` causes VoiceOver to ignore the elements in the view `A`. -On the other hand, if view `B` contains a child view `C` and you set `accessibilityViewIsModal` to `true` on view `C`, VoiceOver does not ignore the elements in view `A`. +For example, in a window that contains sibling views `A` and `B`, setting `accessibilityViewIsModal` to `true` on view `B` causes VoiceOver to ignore the elements in the view `A`. On the other hand, if view `B` contains a child view `C` and you set `accessibilityViewIsModal` to `true` on view `C`, VoiceOver does not ignore the elements in view `A`. + +#### accessibilityElementsHidden (iOS) + +A Boolean value indicating whether the accessibility elements contained within this accessibility element are hidden. + +For example, in a window that contains sibling views `A` and `B`, setting `accessibilityElementsHidden` to `true` on view `B` causes VoiceOver to ignore the elements in the view `B`. This is similar to the Android property `importantForAccessibility="no-hide-descendants"`. #### onAccessibilityTap (iOS) @@ -89,9 +148,15 @@ Use this property to assign a custom function to be called when someone activate Assign this property to a custom function which will be called when someone performs the "magic tap" gesture, which is a double-tap with two fingers. A magic tap function should perform the most relevant action a user could take on a component. In the Phone app on iPhone, a magic tap answers a phone call, or ends the current one. If the selected element does not have an `onMagicTap` function, the system will traverse up the view hierarchy until it finds a view that does. +#### onAccessibilityEscape (iOS) + +Assign this property to a custom function which will be called when someone performs the "escape" gesture, which is a two finger Z shaped gesture. An escape function should move back hierarchically in the user interface. This can mean moving up or back in a navigation hierarchy or dismissing a modal user interface. If the selected element does not have an `onAccessibilityEscape` function, the system will attempt to traverse up the view hierarchy until it finds a view that does or bonk to indicate it was unable to find one. + #### accessibilityComponentType (Android) -In some cases, we also want to alert the end user of the type of selected component (i.e., that it is a “button”). If we were using native buttons, this would work automatically. Since we are using javascript, we need to provide a bit more context for TalkBack. To do so, you must specify the ‘accessibilityComponentType’ property for any UI component. For instances, we support ‘button’, ‘radiobutton_checked’ and ‘radiobutton_unchecked’ and so on. +> **Note:** > `accessibilityComponentType` will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. + +In some cases, we also want to alert the end user of the type of selected component (i.e., that it is a “button”). If we were using native buttons, this would work automatically. Since we are using javascript, we need to provide a bit more context for TalkBack. To do so, you must specify the ‘accessibilityComponentType’ property for any UI component. We support 'none', ‘button’, ‘radiobutton_checked’ and ‘radiobutton_unchecked’. ```javascript ``` -In the above example method _addOne changes the state.count variable. As soon as an end user clicks the TouchableWithoutFeedback, TalkBack reads text in the Text view because of its 'accessibilityLiveRegion=”polite”' property. +In the above example method \_addOne changes the state.count variable. As soon as an end user clicks the TouchableWithoutFeedback, TalkBack reads text in the Text view because of its 'accessibilityLiveRegion=”polite”' property. #### importantForAccessibility (Android) @@ -146,31 +211,37 @@ In the above example, the yellow layout and its descendants are completely invis ### Checking if a Screen Reader is Enabled -The `AccessibilityInfo` API allows you to determine whether or not a screen reader is currently active. See the [AccessibilityInfo documentation](docs/accessibilityinfo.html) for details. +The `AccessibilityInfo` API allows you to determine whether or not a screen reader is currently active. See the [AccessibilityInfo documentation](accessibilityinfo.md) for details. ### Sending Accessibility Events (Android) Sometimes it is useful to trigger an accessibility event on a UI component (i.e. when a custom view appears on a screen or a custom radio button has been selected). Native UIManager module exposes a method ‘sendAccessibilityEvent’ for this purpose. It takes two arguments: view tag and a type of an event. ```javascript +import { UIManager, findNodeHandle } from 'react-native'; + _onPress: function() { - this.state.radioButton = this.state.radioButton === “radiobutton_checked” ? - “radiobutton_unchecked” : “radiobutton_checked”; - if (this.state.radioButton === “radiobutton_checked”) { - RCTUIManager.sendAccessibilityEvent( - ReactNative.findNodeHandle(this), - RCTUIManager.AccessibilityEventTypes.typeViewClicked); + const radioButton = this.state.radioButton === 'radiobutton_checked' ? + 'radiobutton_unchecked' : 'radiobutton_checked' + + this.setState({ + radioButton: radioButton + }); + + if (radioButton === 'radiobutton_checked') { + UIManager.sendAccessibilityEvent( + findNodeHandle(this), + UIManager.AccessibilityEventTypes.typeViewClicked); } } ``` In the above example we've created a custom radio button that now behaves like a native one. More specifically, TalkBack now correctly announces changes to the radio button selection. - ## Testing VoiceOver Support (iOS) To enable VoiceOver, go to the Settings app on your iOS device. Tap General, then Accessibility. There you will find many tools that people use to make their devices more usable, such as bolder text, increased contrast, and VoiceOver. diff --git a/docs/Animations.md b/docs/Animations.md index ad93309..b269a2b 100644 --- a/docs/Animations.md +++ b/docs/Animations.md @@ -1,26 +1,15 @@ --- id: animations title: Animations -layout: docs -category: Guides -permalink: docs/animations.html -next: accessibility -previous: images --- -Animations are very important to create a great user experience. -Stationary objects must overcome inertia as they start moving. -Objects in motion have momentum and rarely come to a stop immediately. -Animations allow you to convey physically believable motion in your interface. +Animations are very important to create a great user experience. Stationary objects must overcome inertia as they start moving. Objects in motion have momentum and rarely come to a stop immediately. Animations allow you to convey physically believable motion in your interface. -React Native provides two complementary animation systems: -[`Animated`](docs/animations.html#animated-api) for granular and interactive control of specific values, and -[`LayoutAnimation`](docs/animations.html#layoutanimation) for animated global layout transactions. +React Native provides two complementary animation systems: [`Animated`](animations.md#animated-api) for granular and interactive control of specific values, and [`LayoutAnimation`](animations.md#layoutanimation-api) for animated global layout transactions. ## `Animated` API -The [`Animated`](docs/animated.html) API is designed to make it very easy to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. -`Animated` focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simple `start`/`stop` methods to control time-based animation execution. +The [`Animated`](animated.md) API is designed to make it very easy to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. `Animated` focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simple `start`/`stop` methods to control time-based animation execution. `Animated` exports four animatable component types: `View`, `Text`, `Image`, and `ScrollView`, but you can also create your own using `Animated.createAnimatedComponent()`. @@ -75,14 +64,9 @@ export default class App extends React.Component { } ``` -Let's break down what's happening here. -In the `FadeInView` constructor, a new `Animated.Value` called `fadeAnim` is initialized as part of `state`. -The opacity property on the `View` is mapped to this animated value. -Behind the scenes, the numeric value is extracted and used to set opacity. +Let's break down what's happening here. In the `FadeInView` constructor, a new `Animated.Value` called `fadeAnim` is initialized as part of `state`. The opacity property on the `View` is mapped to this animated value. Behind the scenes, the numeric value is extracted and used to set opacity. -When the component mounts, the opacity is set to 0. -Then, an easing animation is started on the `fadeAnim` animated value, -which will update all of its dependent mappings (in this case, just the opacity) on each frame as the value animates to the final value of 1. +When the component mounts, the opacity is set to 0. Then, an easing animation is started on the `fadeAnim` animated value, which will update all of its dependent mappings (in this case, just the opacity) on each frame as the value animates to the final value of 1. This is done in an optimized way that is faster than calling `setState` and re-rendering. Because the entire configuration is declarative, we will be able to implement further optimizations that serialize the configuration and runs the animation on a high-priority thread. @@ -91,70 +75,61 @@ Because the entire configuration is declarative, we will be able to implement fu Animations are heavily configurable. Custom and predefined easing functions, delays, durations, decay factors, spring constants, and more can all be tweaked depending on the type of animation. -`Animated` provides several animation types, the most commonly used one being [`Animated.timing()`](docs/animated.html#timing). -It supports animating a value over time using one of various predefined easing functions, or you can use your own. -Easing functions are typically used in animation to convey gradual acceleration and deceleration of objects. +`Animated` provides several animation types, the most commonly used one being [`Animated.timing()`](animated.md#timing). It supports animating a value over time using one of various predefined easing functions, or you can use your own. Easing functions are typically used in animation to convey gradual acceleration and deceleration of objects. -By default, `timing` will use a easeInOut curve that conveys gradual acceleration to full speed and concludes by gradually decelerating to a stop. -You can specify a different easing function by passing a `easing` parameter. -Custom `duration` or even a `delay` before the animation starts is also supported. +By default, `timing` will use a easeInOut curve that conveys gradual acceleration to full speed and concludes by gradually decelerating to a stop. You can specify a different easing function by passing a `easing` parameter. Custom `duration` or even a `delay` before the animation starts is also supported. For example, if we want to create a 2-second long animation of an object that slightly backs up before moving to its final position: ```javascript -Animated.timing( - this.state.xPosition, - { - toValue: 100, - easing: Easing.back, - duration: 2000, - } -).start(); +Animated.timing(this.state.xPosition, { + toValue: 100, + easing: Easing.back(), + duration: 2000, +}).start(); ``` -Take a look at the [Configuring animations](docs/animated.html#configuring-animations) section of the `Animated` API reference to learn more about all the config parameters supported by the built-in animations. +Take a look at the [Configuring animations](animated.md#configuring-animations) section of the `Animated` API reference to learn more about all the config parameters supported by the built-in animations. ### Composing animations -Animations can be combined and played in sequence or in parallel. -Sequential animations can play immediately after the previous animation has finished, -or they can start after a specified delay. -The `Animated` API provides several methods, such as `sequence()` and `delay()`, -each of which simply take an array of animations to execute and automatically calls `start()`/`stop()` as needed. +Animations can be combined and played in sequence or in parallel. Sequential animations can play immediately after the previous animation has finished, or they can start after a specified delay. The `Animated` API provides several methods, such as `sequence()` and `delay()`, each of which simply take an array of animations to execute and automatically calls `start()`/`stop()` as needed. For example, the following animation coasts to a stop, then it springs back while twirling in parallel: ```javascript -Animated.sequence([ // decay, then spring to start and twirl - Animated.decay(position, { // coast to a stop +Animated.sequence([ + // decay, then spring to start and twirl + Animated.decay(position, { + // coast to a stop velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release deceleration: 0.997, }), - Animated.parallel([ // after decay, in parallel: + Animated.parallel([ + // after decay, in parallel: Animated.spring(position, { - toValue: {x: 0, y: 0} // return to start + toValue: {x: 0, y: 0}, // return to start }), - Animated.timing(twirl, { // and twirl + Animated.timing(twirl, { + // and twirl toValue: 360, }), ]), -]).start(); // start the sequence group +]).start(); // start the sequence group ``` -If one animation is stopped or interrupted, then all other animations in the group are also stopped. -`Animated.parallel` has a `stopTogether` option that can be set to `false` to disable this. +If one animation is stopped or interrupted, then all other animations in the group are also stopped. `Animated.parallel` has a `stopTogether` option that can be set to `false` to disable this. -You can find a full list of composition methods in the [Composing animations](docs/animated.html#composing-animations) section of the `Animated` API reference. +You can find a full list of composition methods in the [Composing animations](animated.md#composing-animations) section of the `Animated` API reference. ### Combining animated values -You can [combine two animated values](docs/animated.html#combining-animated-values) via addition, multiplication, division, or modulo to make a new animated value. +You can [combine two animated values](animated.md#combining-animated-values) via addition, multiplication, division, or modulo to make a new animated value. -There are some cases where an animated value needs to invert another animated value for calculation. -An example is inverting a scale (2x --> 0.5x): +There are some cases where an animated value needs to invert another animated value for calculation. An example is inverting a scale (2x --> 0.5x): ```javascript -const a = Animated.Value(1); +const a = new Animated.Value(1); const b = Animated.divide(1, a); Animated.spring(a, { @@ -164,10 +139,7 @@ Animated.spring(a, { ### Interpolation -Each property can be run through an interpolation first. -An interpolation maps input ranges to output ranges, -typically using a linear interpolation but also supports easing functions. -By default, it will extrapolate the curve beyond the ranges given, but you can also have it clamp the output value. +Each property can be run through an interpolation first. An interpolation maps input ranges to output ranges, typically using a linear interpolation but also supports easing functions. By default, it will extrapolate the curve beyond the ranges given, but you can also have it clamp the output value. A simple mapping to convert a 0-1 range to a 0-100 range would be: @@ -178,9 +150,7 @@ value.interpolate({ }); ``` -For example, you may want to think about your `Animated.Value` as going from 0 to 1, -but animate the position from 150px to 0px and the opacity from 0 to 1. -This can easily be done by modifying `style` from the example above like so: +For example, you may want to think about your `Animated.Value` as going from 0 to 1, but animate the position from 150px to 0px and the opacity from 0 to 1. This can easily be done by modifying `style` from the example above like so: ```javascript style={{ @@ -194,13 +164,12 @@ This can easily be done by modifying `style` from the example above like so: }} ``` -[`interpolate()`](docs/animated.html#interpolate) supports multiple range segments as well, which is handy for defining dead zones and other handy tricks. -For example, to get an negation relationship at -300 that goes to 0 at -100, then back up to 1 at 0, and then back down to zero at 100 followed by a dead-zone that remains at 0 for everything beyond that, you could do: +[`interpolate()`](animated.md#interpolate) supports multiple range segments as well, which is handy for defining dead zones and other handy tricks. For example, to get a negation relationship at -300 that goes to 0 at -100, then back up to 1 at 0, and then back down to zero at 100 followed by a dead-zone that remains at 0 for everything beyond that, you could do: ```javascript value.interpolate({ inputRange: [-300, -100, 0, 100, 101], - outputRange: [300, 0, 1, 0, 0], + outputRange: [300, 0, 1, 0, 0], }); ``` @@ -226,22 +195,15 @@ Input | Output ```javascript value.interpolate({ inputRange: [0, 360], - outputRange: ['0deg', '360deg'] -}) + outputRange: ['0deg', '360deg'], +}); ``` -`interpolate()` also supports arbitrary easing functions, many of which are already implemented in the -[`Easing`](docs/easing.html) module. -`interpolate()` also has configurable behavior for extrapolating the `outputRange`. -You can set the extrapolation by setting the `extrapolate`, `extrapolateLeft`, or `extrapolateRight` options. -The default value is `extend` but you can use `clamp` to prevent the output value from exceeding `outputRange`. +`interpolate()` also supports arbitrary easing functions, many of which are already implemented in the [`Easing`](easing.md) module. `interpolate()` also has configurable behavior for extrapolating the `outputRange`. You can set the extrapolation by setting the `extrapolate`, `extrapolateLeft`, or `extrapolateRight` options. The default value is `extend` but you can use `clamp` to prevent the output value from exceeding `outputRange`. ### Tracking dynamic values -Animated values can also track other values. -Just set the `toValue` of an animation to another animated value instead of a plain number. -For example, a "Chat Heads" animation like the one used by Messenger on Android could be implemented with a `spring()` pinned on another animated value, or with `timing()` and a `duration` of 0 for rigid tracking. -They can also be composed with interpolations: +Animated values can also track other values. Just set the `toValue` of an animation to another animated value instead of a plain number. For example, a "Chat Heads" animation like the one used by Messenger on Android could be implemented with a `spring()` pinned on another animated value, or with `timing()` and a `duration` of 0 for rigid tracking. They can also be composed with interpolations: ```javascript Animated.spring(follower, {toValue: leader}).start(); @@ -253,20 +215,13 @@ Animated.timing(opacity, { }).start(); ``` -The `leader` and `follower` animated values would be implemented using `Animated.ValueXY()`. -`ValueXY` is a handy way to deal with 2D interactions, such as panning or dragging. -It is a simple wrapper that basically contains two `Animated.Value` instances and some helper functions that call through to them, -making `ValueXY` a drop-in replacement for `Value` in many cases. -It allows us to track both x and y values in the example above. +The `leader` and `follower` animated values would be implemented using `Animated.ValueXY()`. `ValueXY` is a handy way to deal with 2D interactions, such as panning or dragging. It is a simple wrapper that basically contains two `Animated.Value` instances and some helper functions that call through to them, making `ValueXY` a drop-in replacement for `Value` in many cases. It allows us to track both x and y values in the example above. ### Tracking gestures -Gestures, like panning or scrolling, and other events can map directly to animated values using [`Animated.event`](docs/animated.html#event). -This is done with a structured map syntax so that values can be extracted from complex event objects. -The first level is an array to allow mapping across multiple args, and that array contains nested objects. +Gestures, like panning or scrolling, and other events can map directly to animated values using [`Animated.event`](animated.md#event). This is done with a structured map syntax so that values can be extracted from complex event objects. The first level is an array to allow mapping across multiple args, and that array contains nested objects. -For example, when working with horizontal scrolling gestures, -you would do the following in order to map `event.nativeEvent.contentOffset.x` to `scrollX` (an `Animated.Value`): +For example, when working with horizontal scrolling gestures, you would do the following in order to map `event.nativeEvent.contentOffset.x` to `scrollX` (an `Animated.Value`): ```javascript onScroll={Animated.event( @@ -280,9 +235,7 @@ you would do the following in order to map `event.nativeEvent.contentOffset.x` t )} ``` -When using `PanResponder`, you could use the following code to extract the x and y positions from `gestureState.dx` and `gestureState.dy`. -We use a `null` in the first position of the array, as we are only interested in the second argument passed to the `PanResponder` handler, -which is the `gestureState`. +When using `PanResponder`, you could use the following code to extract the x and y positions from `gestureState.dx` and `gestureState.dy`. We use a `null` in the first position of the array, as we are only interested in the second argument passed to the `PanResponder` handler, which is the `gestureState`. ```javascript onPanResponderMove={Animated.event( @@ -295,31 +248,18 @@ onPanResponderMove={Animated.event( ### Responding to the current animation value -You may notice that there is no obvious way to read the current value while animating. -This is because the value may only be known in the native runtime due to optimizations. -If you need to run JavaScript in response to the current value, there are two approaches: +You may notice that there is no obvious way to read the current value while animating. This is because the value may only be known in the native runtime due to optimizations. If you need to run JavaScript in response to the current value, there are two approaches: -- `spring.stopAnimation(callback)` will stop the animation and invoke `callback` with the final value. This is useful when making gesture transitions. -- `spring.addListener(callback)` will invoke `callback` asynchronously while the animation is running, providing a recent value. - This is useful for triggering state changes, - for example snapping a bobble to a new option as the user drags it closer, - because these larger state changes are less sensitive to a few frames of lag compared to continuous gestures like panning which need to run at 60 fps. +* `spring.stopAnimation(callback)` will stop the animation and invoke `callback` with the final value. This is useful when making gesture transitions. +* `spring.addListener(callback)` will invoke `callback` asynchronously while the animation is running, providing a recent value. This is useful for triggering state changes, for example snapping a bobble to a new option as the user drags it closer, because these larger state changes are less sensitive to a few frames of lag compared to continuous gestures like panning which need to run at 60 fps. -`Animated` is designed to be fully serializable so that animations can be run in a high performance way, independent of the normal JavaScript event loop. -This does influence the API, so keep that in mind when it seems a little trickier to do something compared to a fully synchronous system. -Check out `Animated.Value.addListener` as a way to work around some of these limitations, -but use it sparingly since it might have performance implications in the future. +`Animated` is designed to be fully serializable so that animations can be run in a high performance way, independent of the normal JavaScript event loop. This does influence the API, so keep that in mind when it seems a little trickier to do something compared to a fully synchronous system. Check out `Animated.Value.addListener` as a way to work around some of these limitations, but use it sparingly since it might have performance implications in the future. ### Using the native driver -The `Animated` API is designed to be serializable. -By using the [native driver](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html), -we send everything about the animation to native before starting the animation, -allowing native code to perform the animation on the UI thread without having to go through the bridge on every frame. -Once the animation has started, the JS thread can be blocked without affecting the animation. +The `Animated` API is designed to be serializable. By using the [native driver](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html), we send everything about the animation to native before starting the animation, allowing native code to perform the animation on the UI thread without having to go through the bridge on every frame. Once the animation has started, the JS thread can be blocked without affecting the animation. -Using the native driver for normal animations is quite simple. -Just add `useNativeDriver: true` to the animation config when starting it. +Using the native driver for normal animations is quite simple. Just add `useNativeDriver: true` to the animation config when starting it. ```javascript Animated.timing(this.state.animatedValue, { @@ -329,64 +269,69 @@ Animated.timing(this.state.animatedValue, { }).start(); ``` -Animated values are only compatible with one driver so if you use native driver when starting an animation on a value, -make sure every animation on that value also uses the native driver. +Animated values are only compatible with one driver so if you use native driver when starting an animation on a value, make sure every animation on that value also uses the native driver. -The native driver also works with `Animated.event`. -This is specially useful for animations that follow the scroll position as without the native driver, -the animation will always run a frame behind the gesture due to the async nature of React Native. +The native driver also works with `Animated.event`. This is especially useful for animations that follow the scroll position as without the native driver, the animation will always run a frame behind the gesture due to the async nature of React Native. ```javascript + [ + { + nativeEvent: { + contentOffset: {y: this.state.animatedValue}, + }, + }, + ], + {useNativeDriver: true}, // <-- Add this + )}> {content} ``` -You can see the native driver in action by running the [RNTester app](https://github.com/facebook/react-native/blob/master/RNTester/), -then loading the Native Animated Example. -You can also take a look at the [source code](https://github.com/facebook/react-native/blob/master/RNTester/js/NativeAnimationsExample.js) to learn how these examples were produced. +You can see the native driver in action by running the [RNTester app](https://github.com/facebook/react-native/blob/master/RNTester/), then loading the Native Animated Example. You can also take a look at the [source code](https://github.com/facebook/react-native/blob/master/RNTester/js/NativeAnimationsExample.js) to learn how these examples were produced. #### Caveats -Not everything you can do with `Animated` is currently supported by the native driver. -The main limitation is that you can only animate non-layout properties: -things like `transform` and `opacity` will work, but flexbox and position properties will not. -When using `Animated.event`, it will only work with direct events and not bubbling events. -This means it does not work with `PanResponder` but does work with things like `ScrollView#onScroll`. +Not everything you can do with `Animated` is currently supported by the native driver. The main limitation is that you can only animate non-layout properties: things like `transform` and `opacity` will work, but flexbox and position properties will not. When using `Animated.event`, it will only work with direct events and not bubbling events. This means it does not work with `PanResponder` but does work with things like `ScrollView#onScroll`. + +When an animation is running, it can prevent `VirtualizedList` components from rendering more rows. If you need to run a long or looping animation while the user is scrolling through a list, you can use `isInteraction: false` in your animation's config to prevent this issue. + +### Bear in mind + +While using transform styles such as `rotateY`, `rotateX`, and others ensure the transform style `perspective` is in place. At this time some animations may not render on Android without it. Example below. + +```javascript + +``` ### Additional examples The RNTester app has various examples of `Animated` in use: -- [AnimatedGratuitousApp](https://github.com/facebook/react-native/tree/master/RNTester/js/AnimatedGratuitousApp) -- [NativeAnimationsExample](https://github.com/facebook/react-native/blob/master/RNTester/js/NativeAnimationsExample.js) +* [AnimatedGratuitousApp](https://github.com/facebook/react-native/tree/master/RNTester/js/AnimatedGratuitousApp) +* [NativeAnimationsExample](https://github.com/facebook/react-native/blob/master/RNTester/js/NativeAnimationsExample.js) ## `LayoutAnimation` API -`LayoutAnimation` allows you to globally configure `create` and `update` -animations that will be used for all views in the next render/layout cycle. -This is useful for doing flexbox layout updates without bothering to measure or -calculate specific properties in order to animate them directly, and is -especially useful when layout changes may affect ancestors, for example a "see -more" expansion that also increases the size of the parent and pushes down the -row below which would otherwise require explicit coordination between the -components in order to animate them all in sync. +`LayoutAnimation` allows you to globally configure `create` and `update` animations that will be used for all views in the next render/layout cycle. This is useful for doing flexbox layout updates without bothering to measure or calculate specific properties in order to animate them directly, and is especially useful when layout changes may affect ancestors, for example a "see more" expansion that also increases the size of the parent and pushes down the row below which would otherwise require explicit coordination between the components in order to animate them all in sync. -Note that although `LayoutAnimation` is very powerful and can be quite useful, -it provides much less control than `Animated` and other animation libraries, so -you may need to use another approach if you can't get `LayoutAnimation` to do -what you want. +Note that although `LayoutAnimation` is very powerful and can be quite useful, it provides much less control than `Animated` and other animation libraries, so you may need to use another approach if you can't get `LayoutAnimation` to do what you want. Note that in order to get this to work on **Android** you need to set the following flags via `UIManager`: ```javascript -UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true); +UIManager.setLayoutAnimationEnabledExperimental && + UIManager.setLayoutAnimationEnabledExperimental(true); ``` ```SnackPlayer @@ -455,39 +400,18 @@ const styles = StyleSheet.create({ }); ``` -This example uses a preset value, you can customize the animations as -you need, see [LayoutAnimation.js](https://github.com/facebook/react-native/blob/master/Libraries/LayoutAnimation/LayoutAnimation.js) -for more information. +This example uses a preset value, you can customize the animations as you need, see [LayoutAnimation.js](https://github.com/facebook/react-native/blob/master/Libraries/LayoutAnimation/LayoutAnimation.js) for more information. ## Additional notes ### `requestAnimationFrame` -`requestAnimationFrame` is a polyfill from the browser that you might be -familiar with. It accepts a function as its only argument and calls that -function before the next repaint. It is an essential building block for -animations that underlies all of the JavaScript-based animation APIs. In -general, you shouldn't need to call this yourself - the animation APIs will -manage frame updates for you. +`requestAnimationFrame` is a polyfill from the browser that you might be familiar with. It accepts a function as its only argument and calls that function before the next repaint. It is an essential building block for animations that underlies all of the JavaScript-based animation APIs. In general, you shouldn't need to call this yourself - the animation APIs will manage frame updates for you. ### `setNativeProps` -As mentioned [in the Direction Manipulation section](docs/direct-manipulation.html), -`setNativeProps` allows us to modify properties of native-backed -components (components that are actually backed by native views, unlike -composite components) directly, without having to `setState` and -re-render the component hierarchy. - -We could use this in the Rebound example to update the scale - this -might be helpful if the component that we are updating is deeply nested -and hasn't been optimized with `shouldComponentUpdate`. - -If you find your animations with dropping frames (performing below 60 frames -per second), look into using `setNativeProps` or `shouldComponentUpdate` to -optimize them. Or you could run the animations on the UI thread rather than -the JavaScript thread [with the useNativeDriver -option](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html). -You may also want to defer any computationally intensive work until after -animations are complete, using the -[InteractionManager](docs/interactionmanager.html). You can monitor the -frame rate by using the In-App Developer Menu "FPS Monitor" tool. +As mentioned [in the Direct Manipulation section](direct-manipulation.md), `setNativeProps` allows us to modify properties of native-backed components (components that are actually backed by native views, unlike composite components) directly, without having to `setState` and re-render the component hierarchy. + +We could use this in the Rebound example to update the scale - this might be helpful if the component that we are updating is deeply nested and hasn't been optimized with `shouldComponentUpdate`. + +If you find your animations with dropping frames (performing below 60 frames per second), look into using `setNativeProps` or `shouldComponentUpdate` to optimize them. Or you could run the animations on the UI thread rather than the JavaScript thread [with the useNativeDriver option](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html). You may also want to defer any computationally intensive work until after animations are complete, using the [InteractionManager](interactionmanager.md). You can monitor the frame rate by using the In-App Developer Menu "FPS Monitor" tool. diff --git a/docs/Debugging.md b/docs/Debugging.md index 1b7b4c8..74399ee 100644 --- a/docs/Debugging.md +++ b/docs/Debugging.md @@ -1,11 +1,6 @@ --- id: debugging title: Debugging -layout: docs -category: Guides -permalink: docs/debugging.html -next: performance -previous: timers --- ## Enabling Keyboard Shortcuts @@ -14,9 +9,9 @@ React Native supports a few keyboard shortcuts in the iOS Simulator. They are de ## Accessing the In-App Developer Menu -You can access the developer menu by shaking your device or by selecting "Shake Gesture" inside the Hardware menu in the iOS Simulator. You can also use the `⌘D` keyboard shortcut when your app is running in the iOS Simulator, or `⌘M` when running in an Android emulator. +You can access the developer menu by shaking your device or by selecting "Shake Gesture" inside the Hardware menu in the iOS Simulator. You can also use the `⌘D` keyboard shortcut when your app is running in the iOS Simulator, or `⌘M` when running in an Android emulator on Mac OS and `Ctrl+M` on Windows and Linux. Alternatively for Android, you can run the command `adb shell input keyevent 82` to open the dev menu (82 being the Menu key code). -![](img/DeveloperMenu.png) +![](/react-native/docs/assets/DeveloperMenu.png) > The Developer Menu is disabled in release (production) builds. @@ -51,7 +46,12 @@ Warnings will be displayed on screen with a yellow background. These alerts are As with a RedBox, you can use `console.warn()` to trigger a YellowBox. -YellowBoxes can be disabled during development by using `console.disableYellowBox = true;`. Specific warnings can be ignored programmatically by setting an array of prefixes that should be ignored: `console.ignoredYellowBox = ['Warning: ...'];`. +YellowBoxes can be disabled during development by using `console.disableYellowBox = true;`. Specific warnings can be ignored programmatically by setting an array of prefixes that should be ignored: + +```javascript +import {YellowBox} from 'react-native'; +YellowBox.ignoreWarnings(['Warning: ...']); +``` In CI/Xcode, YellowBoxes can also be disabled by setting the `IS_TESTING` environment variable. @@ -63,7 +63,7 @@ To debug the JavaScript code in Chrome, select "Debug JS Remotely" from the Deve Select `Tools → Developer Tools` from the Chrome Menu to open the [Developer Tools](https://developer.chrome.com/devtools). You may also access the DevTools using keyboard shortcuts (`⌘⌥I` on macOS, `Ctrl` `Shift` `I` on Windows). You may also want to enable [Pause On Caught Exceptions](http://stackoverflow.com/questions/2233339/javascript-is-there-a-way-to-get-chrome-to-break-on-all-errors/17324511#17324511) for a better debugging experience. -> Note: the React Developer Tools Chrome extension does not work with React Native, but you can use its standalone version instead. Read [this section](docs/debugging.html#react-developer-tools) to learn how. +> Note: the React Developer Tools Chrome extension does not work with React Native, but you can use its standalone version instead. Read [this section](debugging.md#react-developer-tools) to learn how. ### Debugging using a custom JavaScript debugger @@ -73,6 +73,19 @@ The debugger will receive a list of all project roots, separated by a space. For > Custom debugger commands executed this way should be short-lived processes, and they shouldn't produce more than 200 kilobytes of output. +## Safari Developer Tools + +You can use Safari to debug the iOS version of your app without having to enable "Debug JS Remotely". + +* Enable Develop menu in Safari: `Preferences → Advanced → Select "Show Develop menu in menu bar"` +* Select your app's JSContext: `Develop → Simulator → JSContext` +* Safari's Web Inspector should open which has a Console and a Debugger + +However, there are some disadvantages: + +1. No sourcemaps when debugging +2. Every time the app is reloaded (using live reload, or by manually reloading), a new JSContext is created. Choosing "Automatically Show Web Inspectors for JSContexts" saves you from having to select the latest JSContext manually. + ## React Developer Tools You can use [the standalone version of React Developer Tools](https://github.com/facebook/react-devtools/tree/master/packages/react-devtools) to debug the React component hierarchy. To use it, install the `react-devtools` package globally: @@ -87,7 +100,7 @@ Now run `react-devtools` from the terminal to launch the standalone DevTools app react-devtools ``` -![React DevTools](img/ReactDevTools.png) +![React DevTools](/react-native/docs/assets/ReactDevTools.png) It should connect to your simulator within a few seconds. @@ -95,15 +108,15 @@ It should connect to your simulator within a few seconds. ### Integration with React Native Inspector -Open the in-app developer menu and choose "Show Inspector". It will bring up an overlay that lets you tap on any UI element and see information about it: +Open the in-app developer menu and choose "Toggle Inspector". It will bring up an overlay that lets you tap on any UI element and see information about it: -![React Native Inspector](img/Inspector.gif) +![React Native Inspector](/react-native/docs/assets/Inspector.gif) However, when `react-devtools` is running, Inspector will enter a special collapsed mode, and instead use the DevTools as primary UI. In this mode, clicking on something in the simulator will bring up the relevant components in the DevTools: -![React DevTools Inspector Integration](img/ReactDevToolsInspector.gif) +![React DevTools Inspector Integration](/react-native/docs/assets/ReactDevToolsInspector.gif) -You can choose "Hide Inspector" in the same menu to exit this mode. +You can choose "Toggle Inspector" in the same menu to exit this mode. ### Inspecting Component Instances @@ -115,7 +128,7 @@ Make sure that the dropdown in the top left corner of the Chrome console says `d Then select a React component in React DevTools. There is a search box at the top that helps you find one by name. As soon as you select it, it will be available as `$r` in the Chrome console, letting you inspect its props, state, and instance properties. -![React DevTools Chrome Console Integration](img/ReactDevToolsDollarR.gif) +![React DevTools Chrome Console Integration](/react-native/docs/assets/ReactDevToolsDollarR.gif) ## Performance Monitor @@ -129,7 +142,7 @@ You can enable a performance overlay to help you debug performance problems by s

Projects with Native Code Only

The remainder of this guide only applies to projects made with react-native init - or to those made with Create React Native App which have since ejected. For + or to those made with expo init or Create React Native App which have since ejected. For more information about ejecting, please see the guide on the Create React Native App repository. @@ -147,11 +160,11 @@ $ react-native log-android You may also access these through `Debug → Open System Log...` in the iOS Simulator or by running `adb logcat *:S ReactNative:V ReactNativeJS:V` in a terminal while an Android app is running on a device or emulator. -> If you're using Create React Native App, console logs already appear in the same terminal output as the packager. +> If you're using Create React Native App or Expo CLI, console logs already appear in the same terminal output as the packager. ## Debugging on a device with Chrome Developer Tools -> If you're using Create React Native App, this is configured for you already. +> If you're using Create React Native App or Expo CLI, this is configured for you already. On iOS devices, open the file [`RCTWebSocketExecutor.m`](https://github.com/facebook/react-native/blob/master/Libraries/WebSocket/RCTWebSocketExecutor.m) and change "localhost" to the IP address of your computer, then select "Debug JS Remotely" from the Developer Menu. @@ -163,46 +176,6 @@ Alternatively, select "Dev Settings" from the Developer Menu, then update the "D > If you run into any issues, it may be possible that one of your Chrome extensions is interacting in unexpected ways with the debugger. Try disabling all of your extensions and re-enabling them one-by-one until you find the problematic extension. -### Debugging with [Stetho](http://facebook.github.io/stetho/) on Android - -1. In ```android/app/build.gradle```, add these lines in the `dependencies` section: - - ```gradle - compile 'com.facebook.stetho:stetho:1.3.1' - compile 'com.facebook.stetho:stetho-okhttp3:1.3.1' - ``` - -2. In ```android/app/src/main/java/com/{yourAppName}/MainApplication.java```, add the following imports: - - ```java - import com.facebook.react.modules.network.ReactCookieJarContainer; - import com.facebook.stetho.Stetho; - import okhttp3.OkHttpClient; - import com.facebook.react.modules.network.OkHttpClientProvider; - import com.facebook.stetho.okhttp3.StethoInterceptor; - import java.util.concurrent.TimeUnit; - ``` - -3. In ```android/app/src/main/java/com/{yourAppName}/MainApplication.java``` add the function: - ```java - public void onCreate() { - super.onCreate(); - Stetho.initializeWithDefaults(this); - OkHttpClient client = new OkHttpClient.Builder() - .connectTimeout(0, TimeUnit.MILLISECONDS) - .readTimeout(0, TimeUnit.MILLISECONDS) - .writeTimeout(0, TimeUnit.MILLISECONDS) - .cookieJar(new ReactCookieJarContainer()) - .addNetworkInterceptor(new StethoInterceptor()) - .build(); - OkHttpClientProvider.replaceOkHttpClient(client); - } - ``` - -4. Run ```react-native run-android ``` - -5. In a new Chrome tab, open: ```chrome://inspect```, then click on 'Inspect device' (the one followed by "Powered by Stetho"). - ## Debugging native code When working with native code, such as when writing native modules, you can launch the app from Android Studio or Xcode and take advantage of the native debugging features (setting up breakpoints, etc.) as you would in case of building a standard native app. diff --git a/docs/Images.md b/docs/Images.md index 9de79b6..e448fae 100644 --- a/docs/Images.md +++ b/docs/Images.md @@ -1,11 +1,6 @@ --- id: images title: Images -layout: docs -category: Guides -permalink: docs/images.html -next: animations -previous: navigation --- ## Static Image Resources @@ -24,6 +19,7 @@ You can also use the `@2x` and `@3x` suffixes to provide images for different sc . ├── button.js └── img + ├── check.png ├── check@2x.png └── check@3x.png ``` @@ -52,89 +48,121 @@ In order for this to work, the image name in `require` has to be known staticall ```javascript // GOOD - +; // BAD var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive'; - +; // GOOD -var icon = this.props.active ? require('./my-icon-active.png') : require('./my-icon-inactive.png'); - +var icon = this.props.active + ? require('./my-icon-active.png') + : require('./my-icon-inactive.png'); +; ``` Note that image sources required this way include size (width, height) info for the Image. If you need to scale the image dynamically (i.e. via flex), you may need to manually set `{ width: undefined, height: undefined }` on the style attribute. ## Static Non-Image Resources -The `require` syntax described above can be used to statically include audio, video or document files in your project as well. Most common file types are supported including `.mp3`, `.wav`, `.mp4`, `.mov`, `.html` and `.pdf` (see the [packager defaults](https://github.com/facebook/react-native/blob/master/packager/defaults.js) file for the full list). +The `require` syntax described above can be used to statically include audio, video or document files in your project as well. Most common file types are supported including `.mp3`, `.wav`, `.mp4`, `.mov`, `.html` and `.pdf`. See [packager defaults](https://github.com/facebook/metro/blob/master/packages/metro-config/src/defaults/defaults.js#L14-L44) for the full list. + +You can add support for other types by creating a packager config file (see the [packager config file](https://github.com/facebook/react-native/blob/master/local-cli/util/Config.js#L68) for the full list of configuration options). A caveat is that videos must use absolute positioning instead of `flexGrow`, since size info is not currently passed for non-image assets. This limitation doesn't occur for videos that are linked directly into Xcode or the Assets folder for Android. ## Images From Hybrid App's Resources -If you are building a hybrid app (some UIs in React Native, some UIs in platform code) you can still use images that are already bundled into the app (via Xcode asset catalogs or Android drawable folder): +If you are building a hybrid app (some UIs in React Native, some UIs in platform code) you can still use images that are already bundled into the app. + +For images included via Xcode asset catalogs or in the Android drawable folder, use the image name without the extension: ```javascript ``` -This approach provides no safety checks. It's up to you to guarantee that those images are available in the application. Also you have to specify image dimensions manually. +For images in the Android assets folder, use the `asset:/` scheme: +```javascript + +``` + +These approaches provide no safety checks. It's up to you to guarantee that those images are available in the application. Also you have to specify image dimensions manually. ## Network Images -Many of the images you will display in your app will not be available at compile time, or you will want to load some dynamically to keep the binary size down. Unlike with static resources, *you will need to manually specify the dimensions of your image*. It's highly recommended that you use https as well in order to satisfy [App Transport Security](docs/running-on-device.html#app-transport-security) requirements on iOS. +Many of the images you will display in your app will not be available at compile time, or you will want to load some dynamically to keep the binary size down. Unlike with static resources, _you will need to manually specify the dimensions of your image_. It's highly recommended that you use https as well in order to satisfy [App Transport Security](running-on-device.md#app-transport-security) requirements on iOS. ```javascript // GOOD - // BAD - + ``` ### Network Requests for Images - If you would like to set such things as the HTTP-Verb, Headers or a Body along with the image request, you may do this by defining these properties on the source object: +If you would like to set such things as the HTTP-Verb, Headers or a Body along with the image request, you may do this by defining these properties on the source object: + +```javascript + +``` - ```javascript - - ``` +## Uri Data Images + +Sometimes, you might be getting encoded image data from a REST API call. You can use the `'data:'` uri scheme to use these images. Same as for network resources, _you will need to manually specify the dimensions of your image_. + +> This is recommended for very small and dynamic images only, like icons in a list from a DB. + +```javascript +// include at least width and height! + +``` ### Cache Control (iOS Only) In some cases you might only want to display an image if it is already in the local cache, i.e. a low resolution placeholder until a higher resolution is available. In other cases you do not care if the image is outdated and are willing to display an outdated image to save bandwidth. The `cache` source property gives you control over how the network layer interacts with the cache. * `default`: Use the native platforms default strategy. -* `reload`: The data for the URL will be loaded from the originating source. -No existing cache data should be used to satisfy a URL load request. -* `force-cache`: The existing cached data will be used to satisfy the request, -regardless of its age or expiration date. If there is no existing data in the cache -corresponding the request, the data is loaded from the originating source. -* `only-if-cached`: The existing cache data will be used to satisfy a request, regardless of -its age or expiration date. If there is no existing data in the cache corresponding -to a URL load request, no attempt is made to load the data from the originating source, -and the load is considered to have failed. +* `reload`: The data for the URL will be loaded from the originating source. No existing cache data should be used to satisfy a URL load request. +* `force-cache`: The existing cached data will be used to satisfy the request, regardless of its age or expiration date. If there is no existing data in the cache corresponding the request, the data is loaded from the originating source. +* `only-if-cached`: The existing cache data will be used to satisfy a request, regardless of its age or expiration date. If there is no existing data in the cache corresponding to a URL load request, no attempt is made to load the data from the originating source, and the load is considered to have failed. ```javascript - + ``` ## Local Filesystem Images -See [CameraRoll](docs/cameraroll.html) for an example of -using local resources that are outside of `Images.xcassets`. +See [CameraRoll](cameraroll.md) for an example of using local resources that are outside of `Images.xcassets`. ### Best Camera Roll Image @@ -142,9 +170,9 @@ iOS saves multiple sizes for the same image in your Camera Roll, it is very impo ## Why Not Automatically Size Everything? -*In the browser* if you don't give a size to an image, the browser is going to render a 0x0 element, download the image, and then render the image based with the correct size. The big issue with this behavior is that your UI is going to jump all around as images load, this makes for a very bad user experience. +_In the browser_ if you don't give a size to an image, the browser is going to render a 0x0 element, download the image, and then render the image based with the correct size. The big issue with this behavior is that your UI is going to jump all around as images load, this makes for a very bad user experience. -*In React Native* this behavior is intentionally not implemented. It is more work for the developer to know the dimensions (or aspect ratio) of the remote image in advance, but we believe that it leads to a better user experience. Static images loaded from the app bundle via the `require('./my-icon.png')` syntax *can be automatically sized* because their dimensions are available immediately at the time of mounting. +_In React Native_ this behavior is intentionally not implemented. It is more work for the developer to know the dimensions (or aspect ratio) of the remote image in advance, but we believe that it leads to a better user experience. Static images loaded from the app bundle via the `require('./my-icon.png')` syntax _can be automatically sized_ because their dimensions are available immediately at the time of mounting. For example, the result of `require('./my-icon.png')` might be: @@ -166,16 +194,20 @@ On the user side, this lets you annotate the object with useful attributes such ## Background Image via Nesting -A common feature request from developers familiar with the web is `background-image`. To handle this use case, simply create a normal `` component and add whatever children to it you would like to layer on top of it. +A common feature request from developers familiar with the web is `background-image`. To handle this use case, you can use the `` component, which has the same props as ``, and add whatever children to it you would like to layer on top of it. + +You might not want to use `` in some cases, since the implementation is very simple. Refer to ``'s [documentation](imagebackground.md) for more insight, and create your own custom component when needed. ```javascript return ( - + Inside - + ); ``` +Note that you must specify some width and height style attributes. + ## iOS Border Radius Styles Please note that the following corner specific, border radius style properties are currently ignored by iOS's image component: diff --git a/docs/Navigation.md b/docs/Navigation.md index fd0dfb3..7e6d8e2 100644 --- a/docs/Navigation.md +++ b/docs/Navigation.md @@ -1,21 +1,13 @@ --- id: navigation title: Navigating Between Screens -layout: docs -category: Guides -permalink: docs/navigation.html -next: images -previous: platform-specific-code --- Mobile apps are rarely made up of a single screen. Managing the presentation of, and transition between, multiple screens is typically handled by what is known as a navigator. -This guide covers the various navigation components available in React Native. -If you are just getting started with navigation, you will probably want to use [React Navigation](docs/navigation.html#react-navigation). React Navigation provides an easy to use navigation solution, with the ability to present common stack navigation and tabbed navigation patterns on both iOS and Android. As this is a JavaScript implementation, it provides the greatest amount of configurability as well as flexibility when integrating with state management libraries such as [redux](https://reactnavigation.org/docs/guides/redux). +This guide covers the various navigation components available in React Native. If you are just getting started with navigation, you will probably want to use [React Navigation](navigation.md#react-navigation). React Navigation provides an easy to use navigation solution, with the ability to present common stack navigation and tabbed navigation patterns on both iOS and Android. -If you're only targeting iOS, you may want to also check out [NavigatorIOS](docs/navigation.html#navigatorios) as a way of providing a native look and feel with minimal configuration, as it provides a wrapper around the native `UINavigationController` class. This component will not work on Android, however. - -If you'd like to achieve a native look and feel on both iOS and Android, or you're integrating React Native into an app that already manages navigation natively, the following libraries provide native navigation on both platforms: [native-navigation](http://airbnb.io/native-navigation/), [react-native-navigation](https://github.com/wix/react-native-navigation). +If you'd like to achieve a native look and feel on both iOS and Android, or you're integrating React Native into an app that already manages navigation natively, the following library provides native navigation on both platforms: [react-native-navigation](https://github.com/wix/react-native-navigation). ## React Navigation @@ -29,112 +21,40 @@ npm install --save react-navigation Then you can quickly create an app with a home screen and a profile screen: -``` -import { - StackNavigator, -} from 'react-navigation'; +```javascript +import {createStackNavigator, createAppContainer} from 'react-navigation'; -const App = StackNavigator({ - Home: { screen: HomeScreen }, - Profile: { screen: ProfileScreen }, +const MainNavigator = createStackNavigator({ + Home: {screen: HomeScreen}, + Profile: {screen: ProfileScreen}, }); + +const App = createAppContainer(MainNavigator); + +export default App; ``` Each screen component can set navigation options such as the header title. It can use action creators on the `navigation` prop to link to other screens: -``` +```javascript class HomeScreen extends React.Component { static navigationOptions = { title: 'Welcome', }; render() { - const { navigate } = this.props.navigation; + const {navigate} = this.props.navigation; return (