When to use TouchableNativeFeedback, TouchableHighlight or TouchableOpacity? - react-native

In React Native, there are at least three ways to make a button: TouchableNativeFeedback, TouchableHighlight and TouchableOpacity. There is also TouchableWithoutFeedback, which the documentation clearly states you should not use because "all the elements that respond to press should have a visual feedback when touched".
TouchableNativeFeedback is Android only and "replaces the View with another instance of RCTView"
TouchableHighlight "adds a view to the view hierarchy"
TouchableOpacity works "without changing the view hierarchy"
Are there any other significant differences between the three? Is one of them the goto component? In what case should you use TouchableHighlight over TouchableOpacity? Are there any performance implications?
I am writing an application right now, and find that all three have a significant delay between tap and the action (in this case a navigation change). Is there any way to make it snappier?

source: https://medium.com/differential/better-cross-platform-react-native-components-cb8aadeba472, by Nick Wientge
TouchableHighlight
• What it does: Darkens or lightens the background of the element when pressed.
• When to use it: On iOS for touchable elements or buttons that have a solid shape or background, and on ListView items.
TouchableOpacity
• What it does: Lightens the opacity of the entire element when pressed.
• When to use it: On iOS for touchable elements that are standalone text or icons with no background color.
TouchableNativeFeedback
• What it does: Adds a ripple effect to the background when pressed.
• When to use it: On Android for almost all touchable elements.

Well, This is how I typically decide what to use:
If I'm building for Android-only, and the component is large enough that the native feedback will be visibly different than using the others then I use TouchableNativeFeedback
If I want to control the opacity on the component or I want the button to have color when touched, and I don't want to control the focused state of some element inside the Touchable, then I use TouchableHighlight. (TouchableOpacity has got some weird parts when you control opacity yourself).
In all other cases, I use TouchableOpacity because it's more "bare" than TouchableHighlight

I think the main essential difference as stated in Docs:
TouchableHighlight must have one child (not zero or more than one). If you wish to have several child components, wrap them in a View.link
TouchableHighlight
TouchableHighlight A wrapper for making views respond properly to
touches. On press down, the opacity of the wrapped view is decreased,
which allows the underlay color to show through, darkening or tinting
the view.
The underlay comes from wrapping the child in a new View, which can
affect layout, and sometimes cause unwanted visual artifacts if not
used correctly, for example if the backgroundColor of the wrapped view
isn't explicitly set to an opaque color.
TouchableOpacity
TouchableOpacity # A wrapper for making views respond properly to
touches. On press down, the opacity of the wrapped view is decreased,
dimming it.

If you want to
highlight button on press — use TouchableHighlight
change button's opacity on press — use TouchableOpacity

Related

How do to use RefreshControl on a view that does not require ScrollView?

I have a React Native View, that I would like to allow the user to refresh by pulling down, this View contains fixed content that fits on one screen without the need to scroll, and I have used flex to position the elements to utilised the hold screen.
A quick google tells me I need a RefreshControl, but it seems this must be used in conjunction with a ScrollView.
When I try to apply these two controls to my View I get undesired effects:
Scrolls bars that I don't need, although these can be disabled via props
Flex now responds in a different way, the flex items dont expand to the container, which makes sense because its a scrollable container.
Help :)
I would indeed reuse RefreshControl in ScrollView, instead creating a RefreshControl behavior yourself.
As you mentioned, scroll indicators can be hidden by setting the correct props. In addition it is possible to disable scrolling with the scrollEnabled flag.
A ScrollView uses a built-in content container that wraps all the views inside. You can set flex style props for this view as well.
<ScrollView contentContainerStyle={{flex: 1}}>
{/* child views */}
</ScrollView>

Create a new touch effect in a React Native button

React Native seems to come with a few built in effects for "touchable" views, such as TouchableOpacity, TouchableNativeFeedback etc. but none of them fit my use case.
Is there an obvious way to change the styles on a button as it's depressed (change the background color or enlarge the button using transform:scale etc.)? Obviously I'd want it to revert to the default styles when the user stops holding the button.

Animating during momentum scroll in react-native?

I'm attempting to create a custom NavBar on a screen that renders a ScrollView. Inside the NavBar, there's a button, that when pressed, causes the NavBar to translate downwards, thereby giving the appearance that the NavBar is expanding (This is done using Animated.spring() with the useNativeDriver option). Everything is working great, except if the ScrollView is still scrolling at the time the button is tapped (ie: when "momentum" scroll is taking place). In this scenario, the onPress handler that kicks off the NavBar animation is invoked as expected, but calls to Animated.spring() do not cause any animation to take place. Is it possible to either have the NavBar "expansion" animation to occur during the scroll, or pause the scroll to allow animation to proceed?
Like it's explained in RN docs the animation type you using are stoped by gesture events like scrolling, better use Animated.event() with onScrollprops combined with an interpolation animation to animate you footer.

KeyboardAvoidingView hides view instead of showing them

I'm experiencing a very stupid behavior from KeyboardAvoidingView.
Basically every time I focus a TextInput, the screen seems to move of the same height (probably the keyboard height) whatever the position of the TextInput.
Meaning that if a view will be visible after the keyboard shows (and therefore moving the screen is not necessary) KeyboardAvoidingView still moves the screen up, hiding the TextInput behind the ActionBar (or simply outside of the screen).
I tried KeyboardAwareScrollView which works much better... only on iOS.
On Android it does not work at all, just no effects.

How can I activate a touchableOpacity or other react-native component by dragging over it?

I am working on a grid view that consists of touchable opacities side by side. I would like to be able to drag across them and active the onPress function for each. Any ideas? I haven't found anything that works.
Thanks!