I have created a custom button component that should respond to touches. It works as expected on iOS, however on Android it doesn't show up at all. While trying to find the cause of this issue.
I created two snacks on expo to demonstrate the issue. The first is the element wrapped in a Touchable element, and the second is the element without it.
In the first snack, it works as expected in iOS, however it is not shown on Android.
In the second snack, it appears as expected on both, however it is not clicking
https://snack.expo.io/#shepherdjerred/button-with-touchable
https://snack.expo.io/#shepherdjerred/button-without-touchable
For the first snack, add style={{flex: 1}} to the first view component. Flex adjusts a component based on the amount of space available in the application's screen.
return (
<TouchableWithoutFeedback onPressIn={this.handlePressIn.bind(this)}
onPressOut={this.handlePressOut.bind(this)}>
<View style={{flex: 1}}>
<View
style={[
this.stylesheet.buttonLayer,
this.stylesheet.buttonShadow
]}>
</View>
<View
style={[
this.stylesheet.buttonLayer,
this.stylesheet.buttonDepth
]}>
</View>
<View
style={[
this.stylesheet.buttonLayer,
this.stylesheet.buttonTop,
this.state.isPressed ? this.stylesheet.buttonTopPushed : this.stylesheet.buttonTopUnpushed
]}>
</View>
</View>
</TouchableWithoutFeedback>
);
}
For the second snack, the React Native website has two ways of creating buttons or components that can be touched.
References:
Facebook Inc. "Height and Width". React Native.
https://facebook.github.io/react-native/docs/height-and-width.html
(accessed April 2, 2018).
Facebook Inc. "Handling Touches". React Native.
https://facebook.github.io/react-native/docs/handling-touches.html
(accessed April 2, 2018).
https://stackoverflow.com/a/44063868/8121551 (accessed April 2,
2018).
Related
I have a GeoJSON data of lakes and rivers. I am displaying them using the code below.
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
/>
This component renders the data in the map like the image below.
MapView.Geojson Component display example
I want a popup to appear when a user clicks anywhere inside this lake, like a marker.
What I have tried:
I wrapped MapView.Geojson with TouchableOpacity component, to use
its onPress attribute.
<TouchableOpacity onPress={onPress}>
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
></MapView.Geojson>
</TouchableOpacity>
I used onPress attribute of the MapView.Geojson
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
onPress={onPress}
></MapView.Geojson>
I put a Callout component inside the MapView.Geojson with text
<MapView.Geojson
geojson={barajVeGolet}
strokeColor="#39A2DB"
fillColor="#D0E8F2"
strokeWidth={3}
>
<MapView.Callout>
<View style={{ width: 200 }}>
<Text style={styles.barajInfoTitle}>Test</Text>
</View>
</MapView.Callout>
</MapView.Geojson>
Is there any way to click anywhere inside a Geojson or Polygon component which opens a popup, just like the Marker component?
Unfortunately, you cannot set custom callout while using GeoJson of the its Marker module does not supporting it.
https://github.com/react-native-maps/react-native-maps/blob/master/lib/components/Geojson.js#L156
However, you can use custom solution for this use-case.
I've added the onPress functionality for GeoJson
<Geojson
tappable
image={require("assets/markers/bicycle/seasonal-tour.png")}
geojson={your-data}
strokeColor={colors.theme.light.routeColor}
strokeWidth={7}
onPress={(data: any) => {
this.props.myInfoModal.openModal(); // For Modalize
this.setState({modalVisibility: true }); // For Classic Modal
}}
/>
You can use classic modal or modalize
https://github.com/react-native-modal/react-native-modal
https://github.com/jeremybarbet/react-native-modalize
Then you can show the data detail into
I'm using
React Native
OneSignal for push notifications
React Navigation
React Native Elements (Badge component)
React Native Vector Icons
Firebase, Firestore as backend
So, inside my app I have two buttons in my topRight Stack Screen
<Stack.Screen
name="CreateEvent"
component={CreateEvent}
options={{
headerRight: () => (
<View style={{ flexDirection: "row", alignItems: "center", marginRight: 10 }}>
<TouchableOpacity
onPress={() => { navigation.navigate("InvitationsNav") }}>
<Badge
status="error"
containerStyle={{ position: 'absolute', top: -4, right: -4 }}
value="10"/> // <--- hardcoded value
<IconMaterialIcons
name="event"
color={Constants.colors.primaryColor}
backgroundColor="transparent"
size={30}
style={{ paddingHorizontal: 10 }}/>
</TouchableOpacity>
<TouchableOpacity
onPress={() => { navigation.navigate("nl_Notifications") }}>
<Badge
status="error"
containerStyle={{ position: 'absolute', top: -4, right: -4 }}
value="2"/> // <--- hardcoded value
<IconIonicons
name="notifications-outline"
color={Constants.colors.primaryColor}
backgroundColor="rgba(52, 52, 52, 0.0)"
size={30}
style={{ paddingHorizontal: 10 }}/>
</TouchableOpacity>
</View>)
On last image the values are hardcoded.
I want to set those two values dynamically according to not seen firestore documents. I mean if user has not seen those last notifications or events, set that amount of documents not seen on the corresponding badge.
If there are 3 new notifications for that specific user, I want to set a 3 programmatically on the badge.
Or if there are 6 not seen events for that user, I want to set that value on the badge.
Any idea how can I solve this issue?
I guess a solution is to add a flag on the firestore document something like:
seen: false
and when user press over the notificiation or event change that flag to true, but with this solution I have to pre-load firestore documents with seen == false and I'm not sure that is an economic solution.
Is there any way to set this two values just with the OneSignal Push notification? or maybe another solution ?
Thanks in advance!!
What you mentioned here:
but with this solution I have to pre-load firestore documents with seen == false and I'm not sure that is an economic solution.
This statement is not true, documents in firestore are not required to have an equal structure amongs themselves so you can apply that logic only to new documents (or you could add that to older documents for data consistency only, since the documents will never be "unseen", which I don't think it's a requirement in this case).
I am not familiar with the use of OneSignal for push notifications so I can't say if there is a better solution using that, but as far as Firestore solutions go and since you are still going to need to interact with Firestore somehow to check if the documents are still unseen, the flag option is a perfectly fine solution.
I am working on a react-native application with react-native-maps and I would like to have the active marker (i.e. the one I click on and has the callout bubble open) to have a different color than the other markers.
I was able to change the color of the current marker by saving the ref to a state and comparing it when rendering the color (our keys coming back from the server are not trustworthy, so I'm using the ref for now, until the backend developers come up with an ID in the response), but I am stumbling into the following issue:
When I click somewhere else on the map to dismiss the callout, I was not able to set the marker color back to the previous one (I want them all to be at full opacity initially, then set the "inactive" ones to 50% opacity, until the callout is dismissed).
I have gone all over the docs and examples in react-native-maps but could not find any ways of hooking the state change event to the dismiss event.
Here is the current code I have for the Marker:
<Marker
key={index}
coordinate={loc.coordinate}
ref={ref => loc.ref = ref}
opacity={activeMarkerRef === null || activeMarkerRef === loc.ref ? 1 : 0.5}
onPress={() => setActiveMarkerRef(loc.ref);}
>
<Callout
tooltip
style={styles.bubbleView}
>
<MapInfoBubble>
<Text style={styles.bubbleTitle}>{loc.name}</Text>
<Text>
<Text style={styles.descrTitle}>Address: </Text>
<Text>{loc.address}</Text>
</Text>
<Text>
<Text style={styles.descrTitle}>Postal Code: </Text>
<Text>{loc.postal_code}</Text>
</Text>
</MapInfoBubble>
</Callout>
</Marker>
))}
</MapView>
Cant You use the onPress prop for the MapView component and set the selected marker state value back to null.By doing this a re-render would fix your problem
I'm new to react-native so this.setstate method is not predictable for me.
I'm selecting a list of Venue on dropdown 1
according to the venue , the number of available days must be shown as options on the second dropdown.
and similarly according to the second one i have to set timeslots avaiable on the third dropdown
the 2nd to 3rd dropdown works fine for me
but when i select the venue on the first dropdown the 2nd one does not updates. this .setstate is working late there
if i select the venue once more the previously selected days loads not the current one. like setstate method is lagging one step behind
Must be the way i wrote the code ,
I am open to corrections, new structure of coding , anything
but very much in need to get this work
onVenueSelect(index,value){
var props=this.props;
console.log('On venue Select................................')
console.log('index'+index)
console.log('value'+value)
console.log(this.state.venue_id_array[index])
props.getFixtureSlots(this.state.venue_id_array[index], this.state.game_type, this.state.game);
this.setState({selected_venue_id:this.state.venue_id_array[index]})
var days=[];
var timeslots=props.GETFIXTURETIME.timeslot;
for(var i in timeslots){
days.push(timeslots[i].day_of_week);
}
this.setDay_array(days);
this.refs.modal_dayselect.select(-1);
this.setState({selected_venue:value});
}
onDaySelect(index,value){
this.refs.modal_hrsselect.select(-1);
this.props.getFixtureSlots(this.state.selected_venue_id, this.state.game_type, this.state.game);
var props=this.props;
this.setState({selected_day_no:this.state.day_no_array[index]})
console.log(this.state.day_no_array[index])
this.setState({selected_day:value})
}
render_center_selection(){
return(
this.props.selecteddays_array.map((a, i) => {
return( <View key={i} style={{ height:40, borderBottomWidth:2, borderBottomColor: '#ededed' }}>{
<View style={{flexDirection:'column'}}>
<View style={{flexDirection:'row'}}>
<ModalDropdown
style={styles.selection}
defaultValue='Venue'
textStyle={{width:200,fontSize:20,textAlign:'center',color: '#7070D8'}}
dropdownStyle={styles.dropdownstyle}
dropdownTextStyle={{width:350,fontSize:20,textAlign:'center',backgroundColor: '#FDD60B',}}
options={this.state.venue_name_array}
onSelect={(index,value)=>{this.onVenueSelect(index,value)}}/>
<ModalDropdown
ref="modal_dayselect"
style={styles.dayselection}
defaultValue='Day'
textStyle={{width:50,fontSize:15,textAlign:'center',color: '#7070D8'}}
dropdownStyle={styles.daydropdownstyle}
dropdownTextStyle={{width:50,fontSize:15,textAlign:'center',backgroundColor: '#FDD60B',color: '#7070D8'}}
options={this.state.day_array}
onSelect={(index,value)=>{this.onDaySelect(index,value)}}/>
<ModalDropdown
ref="modal_hrsselect"
style={styles.dayselection}
defaultValue='HRS'
textStyle={{width:50,fontSize:15,textAlign:'center',color: '#7070D8'}}
dropdownStyle={styles.daydropdownstyle}
dropdownTextStyle={{width:50,fontSize:15,textAlign:'center',backgroundColor: '#FDD60B',color: '#7070D8'}}
options={this.state.hrs_array}
onSelect={(index,value)=>{this.setState({selected_hr:value})}}/>
</View>
</View>
}</View>);
})
);
}
First thing you have to do is to remove all console.log statements from your code. It really helpful but slows down the app rendering/refreshing rate.
Second thing and the most important thing is to consolidate state setting calls. ie, you only need one setState call inside one action. For every setState call the app re-renders the parts which uses that changed state. So, update multiple states at once otherwise it will not be detected by the react.
I'm writing an application and only want the back button to show when I push new views onto the Navigator (in this case a news article vs. a list of news articles).
It seems like the way to do this would be to modify render() to only include the Back button for certain navigator states. And while the React Native docs suggest components inside the navigator can access it using getContext, this doesn't seem to work for navigatorBar.
Is this the right way to go about it? How would I render the Back button only for certain navigation states?
<Navigator
initialRoute={{name: 'NewsList', index: 0}}
renderScene={this.renderScene}
sceneStyle={styles.navigator}
navigationBar={
<View style={styles.navbar}>
<View style={styles.logo_container}>
<Text style={styles.backButton}>Back</Text>
<Image
source={require( 'image!Logo' )}
style={styles.logo}
/>
</View>
<View style={styles.separator} />
</View>
}
/>
It will help to move your navigationBar code into its own component, pass the route information into it*, then check for route depth.
TLDR;
if (route.index > 0){
//Show Back Button.
}
Or just make your life easier and user either of these plugins to do the job for you.
React-Native-NavBar https://github.com/Kureev/react-native-navbar
React-Native-Router https://github.com/t4t5/react-native-router
*Passing the route may no longer be needed since the addition of Navigator.getContext(this).xxx was added. See navigator documentation for further info on getContext https://facebook.github.io/react-native/docs/navigator.html