How to access OnPress event that happens outside the component? - react-native

I am creating a custom dropdown component in React Native. I want to close it contents, when user presses screen outside of the component on any other part of the application.
However, I cannot know if user pressed outside the component. Is there a global OnPress event that can accessed or some other way, kindly let me know.

Edited:
add a logic when you click dropdown it should create a transparent view covering wholescreen in a absolute position.
Do it Like this:
// inside render
<Fragment>
<Nested>
<DropDown/>
</Nested>
{isDrop &&
<View style={styles.container} // height:'100%', width:'100%', backgroundColor:transparent , position: 'absolute'
//Trigger for pressing outside DropDown
onResponderStart={() => { condition for dropdown}}
//Required to start interacting with touches
onStartShouldSetResponder={(e) => {return true}}/>}
</Fragment>
DropDown component and view with touch must be the same level

Related

React native partial modal

I am working on a react-native app using react navigation.
I want to add a partial modal that covers 30% of screen when pressing on one of the tabs in the bottom-tab, similar to the "+" tab in the YouTube app:
Youtube modal
I've tried to use react-native Modal component, but
I have problems with activating it from bottom tab
it covers whole screen
Any suggestions?
Thanks..
To answer your question 100% correct I'd need to know more details about your project but, I can try to explain how can be your logic to do this withou any libs.
You can create another component called "Start" where you're gonna put your Modal with absolute position above your navigator.
You can create a Modal that will be above your navigator:
export const Start(){
return(
<View style={{flex:1}}>
<Modal>
<View/>
</Modal>
<NavigatorComponent/>
</View>
)
}
This is going to work because when you put a component with absolute position above the other, this component stay in front of the below component. In your case, will stay in front of everything including the TabBar.
To the modal has just 30% of the height you just need to put in its styles the attribute height: '30%'.
In the initial component of your App (usually the index.js file), you just return the new Start component.
I hope you like my answer. Please, if you have more questions you can ask. Waiting for your feedback :).

How to prerender a component in react-navigation before switching to it?

Inside my StackNavigator, one of the components includes web content with a long loading time. However, this screen will only be shown late in my navigation flow.
How can I use this time to render my component in the background before finally switching to it?
I couldn't find anything comparable to ReactDOM.render in React Native that would allow me to render it manually.
I am not aware of any option in react-navigation to preload a screen that is not displayed, except maybe when the screen is part of a tab navigator.
Depending on what is slowing down the rendering, you might be able to do some actions in the first screen and later pass the results to the second screen using a navigation parameter.
For instance, if you are fetching data from an api in the second screen, you could fetch this data in the first screen and pass it to the second one:
this.props.navigation.navigate('SecondScreen', { data: this.data });
If it is a component, you could also try to build it in the first screen and pass it in the same fashion:
this.props.navigation.navigate('SecondScreen', { component: this.component });
If you are rendering a WebView in the second screen, what can help is to render the WebView in the first screen too, but with no width or height. The WebView will not be displayed but the website data will be fetched and cached, making the real render more efficient:
render() {
return (
<View>
<WebView source={{ uri: 'https://github.com/facebook/react-native' }} style={{ height: 0, width: 0 }} />
{this.renderCurrentScreen()}
</View>
);
}

Implementing a scale screen transition with React Native?

Im trying to implement a screen transition effect, when a user clicks on a Box Component (inside a ScrollView), the image will scale and move to the top, Airbnb has a great example of this:
Airbnb scale transition
<ScrollView>
<Box /> // onPress the scaleImage comp should move to top screen
<Box /> // regardless of scroll position
<Box />
<Box />
...
</ScrollView>
<Animated.Image
style={styles.scaleImage}
source={this.state.activeImage} />
I know how to implement the animation part of this, but the problem Im having is the layout, if the images that Im trying to scale and move to the top are in a ScrollView, how can I determine the distance to get to the top.
You could try using React Native's measure function. You can give it any native component (View, ListView, Image, etc.) and it will give you that component's offsets to its frame (the native view which contains it), its page (the screen borders), and its width/height in a callback as soon as rendering is done (or immediately, if rendering is already done)
To get a reference to your image component, define it as:
<Image ref="myImage" /*...*/ />
Then, within your component class, you can do:
this.refs.myImage.measure((frameX, frameY ,width, height, pageX, pageY) => {
//do stuff with the measurements
})
In your case, you would likely want to use pageX and pageY as they will give you the absolute position of your image. Just remember this function only works on native components and not on user-defined components, so you should call it on the actual Image component and not on any wrappers you define around it.

TabBarIOS - Is there a viewDidAppear or viewWillAppear equivalent?

Specifically for writing a callback from within a child component of a TabBarIOS.item that is triggered when a Tab is selected. (TabBarIOS in React Native)
There is no callbacks for ViewDidAppear and ViewWillAppear for tabs. You can pass a prop like isTabAcitve in TabIOSItem child component. And implement your child component depending upon isTabActive value. Your code TabBarIOSItem can look something like this:
<TabBarIOS.Item
title=""
selected={this.isTabActive("my-account-tab")}
icon={require("./img/user-tab.png")}
onPress={() => {
this.setState({activeTab:"my-account-tab"});
}}>
<MyAccountTabisTabActive={this.isTabActive("my-account-tab")} />
</TabBarIOS.Item>
isTabActive can be a method in your component containing TabIOS:
isTabActive(tabName)
{
return this.state.activeTab == tabName;
}
Also TabBarIOS don't render all tabs at once, A TabBarIOS child component is initialised and mounted for first time only when that tab is pressed for first time. So componentWillMount and componentDidMount can also be used as alternative of viewDidAppear and viewWillAppear.

Is there a way in which I can ignore touch events on Text in React Native?

I want to implement floating labels, for this I have a Text Component Above a TextInput. I want to ignore all the touch events on the Text so that the TextInput under it gets all the events. Is there a way I can do this ? In CSS we used to have pointer-events: none, I am not sure how to do this in React Native.
In react-native, pointerEvents is a prop, not a style.
<View pointerEvents="none" />
Add pointerEvents: 'none' to the Text component. This allows touch events to go to the ancestors of the component, but not the component itself or its children.
React Native also supports 'box-none', which allows touch events to go to the ancestors and children of the component, and excludes only the component itself.
I had the same problem as Cryszon. On Android is seems like pointerEvents="none" doesn't work for Text components.
Wrapping the Text in a View and putting the pointerEvents="none" prop there solved it.
pointerEvents work only on View not on Text or TouchableOpacity.
If you have an issue where even 'box-none' doesn't allow touch events to go to the children, you could do something like this
let setPointerEvents = 'none';
...
<View pointerEvents={setPointerEvents}>
...
<TouchableOpacity onPress= {()=>this.set(false)}/>
</View>
<TouchableOpacity onPress= {()=>this.set(true)}/>
...
set(bool){
switch(bool){
case true:
setPointerEvents= 'auto'
break;
case false:
setPointerEvents= 'none'
break;
}
}
Kind of a hack, but it works.