Is there a property that makes Ionicons have some press feedback? - react-native

I'm using Ionicons from #expo/vector-icons in some parts of my application. I'm trying to ensure that all pressable elements in my UI have some sort of visual feedback. I checked the vector-icons API and didn't find any relevant properties but I just want to ensure I know the best way to achieve this.
My guess is that I would have to wrap all of the <Ionicons /> in a TouchableOpacity or another component of its type, other than TouchableWithoutFeedback. Is this correct? Is there a more direct way to achieve this? And is my suggestion the way to go?
I don't think code is relevant here, but here it is anyway:
import React from 'react'
import { StyleSheet } from 'react-native'
import { Ionicons } from '#expo/vector-icons'
import PropTypes from 'prop-types'
const HeaderIcon = (props) => {
return (
<Ionicons
style={styles.icon}
name={props.name}
color={props.color}
onPress={() => {
props.onPress()
}}
/>
)
}

You can wrap your icon component with TouchableHighlight
it has underlayColor property where you can pass color.
e.g
<TouchableHighlight onPress={onPress} underlayColor="red">
<View style={styles.button}>
<Text>Touch Here</Text>
</View>
</TouchableHighlight>
and also have two other underlay callbacks such as onShowUnderlay and onHideUnderlay these callbacks can be used in different scenarios
Like onShowUnderlay you can change icon color or trigger any other function.

Related

React Native how to remove the blue glow outline on input component

I have a react native project (react native for macOS) I am using the input component but notice there is a blue outline. Not sure how to remove it. I am using Native base input component which I am told it's using the react native input component. How can I remove the ugly blue outline when focus. I am mainly trying to remove the one that is square
import React from 'react';
import {Icon, Input} from 'native-base';
import Ionicons from 'react-native-vector-icons/Ionicons';
const SearchBar = () => {
return (
<Input
variant="rounded"
size="xs"
// w={{
// base: '75%',
// md: '25%',
// }}
InputLeftElement={
<Icon
as={<Ionicons name="ios-search" />}
size={5}
ml="2"
color="muted.400"
/>
}
placeholder="Search"
/>
);
};
export default SearchBar;
When using a React native TextInput component the css styling outline: "none" can be used to remove the outline on focus. This can be done by passing it directly into the style prop.
<View style={styles.body}>
<TextInput
style={{ outline: "none" }}
placeholder="Text"
onChangeText={(newText) => setText(newText)}
value={text}
/>
</View>
);
}
However since you are using a custom component you will need to make sure that the styles are passed to the component.

How would you do that opening effect with React Native?

Imagine a feed of items and then you click on one item and it opens in this way. We need to create a news app that has this identical animation (check sec 00:13 of video linked). enter link description here
You can use the react-native-collapsible package to achieve something like this
https://github.com/oblador/react-native-collapsible
One way to do this is to do dynamic styling.
like this:
import React from "react";
import { View, TouchableOpacity} from "react-native";
const Component = () => {
const [isOpen, setisOpen] = React.useState(false);
return (
<TouchableOpacity onPress={() => setisOpen(!isOpen)}>
<View>
{/* The View content that is always open */}
</View>
<View style={isOpen ? { disply: "flex" } : { disply: "none" }}>
{/* The View content to be opened/hidden */}
</View>
</TouchableOpacity>
);
};
then you can just import this component in your screen like this:
<Component />
Depend on the navigation library you are using but I will assume that you are using react-navigation.
You have this package to perform an animation with shared element during navigation between two screens: https://github.com/IjzerenHein/react-navigation-shared-element.
Very easy to use and very performant.

React Native Elements - Wrapping a touchable opacity around an input does not work in IOS

I am having a very peculiar issue with React Native Elements Text Input along with using touchable opacity.
import React, { useState } from 'react';
import { TouchableOpacity, View, Dimensions } from 'react-native';
import { Input } from 'react-native-elements';
const test = () => (
<TouchableOpacity onPress={() => console.log('we hit here')}>
<Input disabled>
{children}
</Input>
</TouchableOpacity>
)
export default test;
So the outer rim of the input field is completely clickable, however, the center of the component, it cannot be clicked.
This works perfectly for android however.
Any ideas
if anyone has this issue, then the you need to supply a pointerEvents to 'none' for the entire component to be clickable:
<View pointerEvents='none'>
<Input disabled>
{children}
</Input>
</View>
Mubeen hussain answer is correct, but to be more precise it's like this
<TouchableOpacity onPress={() => console.log('we hit here')}>
<View pointerEvents="none">
<Input disabled>{children}</Input>
</View>
</TouchableOpacity>

ReactNative Cannot update a component from inside the function body of a > different component

My HomeHeader component is like this:
import React from "react";
import { View, StyleSheet, Text, Image } from "react-native";
import Icon from "react-native-vector-icons/FontAwesome5";
export default function HomeHeader({ navigation }) {
return (
<View style={styles.home_header}>
<Icon
style={styles.menu}
name="bars"
size={30}
color="white"
onPress={navigation.toggleDrawer()}
/>
<Image
style={styles.header_logo}
source={require("../assets/logo.png")}
/>
<Text>Hello</Text>
</View>
);
}
And am using it in my Home screen like this:
return (
<View>
<HomeHeader navigation={navigation} />
</View>
)
But am receiving this error message:
Warning: Cannot update a component from inside the function body of a
different component.
What am trying to do is, I have separated out the header section of my HOME screen into a separate component called HomeHeader. And in this component, am attaching the event handler to toggle the opening/closing of the DrawerNavigation (left side drawer menu)
If I create a Button in my HOME screen and add the event handler to toggle the drawer, it works fine. But the issue happens only if I try this from inside my HomeHeader component.
Btw, am using ReactNavigation v5 and I even tried this method: https://reactnavigation.org/docs/connecting-navigation-prop/
No luck so far.
Change onPress={ navigation.toggleDrawer() } to onPress={ ()=> navigation.toggleDrawer() }
You can read more about this in here

How to disable highlighting effect of TouchableOpacity when scrolling?

<TouchableOpacity style={{ flex: 1 }} >
<ImageBackground
source={require('../../images/home.jpg')}>
<View style={styles.item} collapsable={false}>
<H3>{contentData[i].name}</H3>
<Text>{contentData[i].description}</Text>
</View>
</ImageBackground>
</TouchableOpacity>
I have a list of TouchableOpacity inside a ScrollView. I want to disable highlighting effect of TouchableOpacity. When scrolling I want to highlight only when onPress event is triggered. Because it may confuse the user that it is pressed.
Simply pass activeOpactity prop with value 1.
<TouchableOpacity activeOpacity={1}>....</TouchableOpacity>
Make sure you import TouchableOpacity from "react-native" not from "react-native-gesture-handler".
Try setting the activeOpacity prop on the TouchableOpacity to 1 when scrolling. Use default settings when the user stops scrolling.
https://facebook.github.io/react-native/docs/touchableopacity#activeopacity
You can try changing param delayPressIn. Look doc.
<TouchableOpacity delayPressIn={150} >
{children}
</TouchableOpacity>
You can make use of onScrollBeginDrag and onScrollEndDrag props.
state = {
scrollBegin: false
}
scrollStart = () => this.setState({scrollBegin: true})
scrollEnd = () => this.setState({scrollBegin: false})
<ScrollView onScrollBeginDrag={this.scrollStart} onScrollEndDrag={this.scrollEnd}>
... Other stuff
</ScrollView>
and set activeOpacity={1} for TouchableOpacity when this.state.scrollBegin=true
You could try replace TouchOpacity with RectButton in 'react-native-gesture-handler'. And don't forget to replace the ScrollView import from 'react-native' to 'react-native-gesture-handler'.
I found this solution in here.
It just said:
provides native and platform default interaction for buttons that are placed in a scrollable container (in which case the interaction is slightly delayed to prevent button from highlighting when you fling)
We implemeted a custom Touchable component using TouchableOpacity as click element and a wrapper View handling the opacity of the children elements.
By setting activeOpacity={1} to default and the pressed state to true when clicking, we can delay the rest of the onPress functionality by a unnoticeable 100ms to display an opacity shift when clicking. Which is shipped to the wrapper View. The View is wrapped inside the touchable instead of outside to better preserve styling.
We also added cleanup when component is unmounted in useEffect()
import React, { useEffect, useState } from "react";
import { View, TouchableOpacity } from "react-native";
const Touchable = (props) => {
const { children, onPress } = props;
const [pressed, setPressed] = useState(false);
useEffect(() => {
return setPressed(false);
}, []);
return (
<TouchableOpacity
{...props}
activeOpacity={1}
onPress={() => {
setPressed(true);
setTimeout(() => {
setPressed(false);
onPress();
}, 100);
}}
>
<View style={{opacity: pressed ? 0.8 : 1}}>
{children}
</View>
</TouchableOpacity>
);
};
export default Touchable;
I had the same issue, so I wrote this class that I use instead of <TouchableOpacity> in my code:
import React, { Component } from 'react';
import { TouchableOpacity } from 'react-native';
import TimerMixin from 'react-timer-mixin';
class TouchableOpacityScrollable extends Component {
_onPress() {
const { onPress } = this.props;
// Looking in the TouchableOpacity source code we see that
// the touch Opacity is 150, and that it comes back in 250 milliseconds.
// #see https://github.com/facebook/react-native/blob/c416b40542ece64e26fb2298485ae42eeebc352a/Libraries/Components/Touchable/TouchableOpacity.js
this.refs.touchableOpacity.setOpacityTo(0.2, 150);
TimerMixin.setTimeout(() => {
onPress();
this.refs.touchableOpacity.setOpacityTo(1, 250);
}, 150);
}
render() {
const { style, children } = this.props;
return (
<TouchableOpacity
ref="touchableOpacity"
style={style}
activeOpacity={1.0}
onPress={() => this._onPress()}
>
{children}
</TouchableOpacity>
);
}
}
export default TouchableOpacityScrollable;
You will have to install react-timer-mixin to prevent possible crashes.
Enjoy!
after upgrading RN version to 0.63.2 TouchableOpacity is working like it should, during scrolling, hover effect doesn't appears