React Native: component on top of another component - ios

I'm building a location based iOS app using react-native-maps and react-native-google-places-autocomplete.
In my code, I have the search bar code first and the map code second - this is so the search bar renders on top of the map. The problem is, I can't move the map because the search bar component seems to have a transparent element that takes up the whole screen. When the search bar is removed, I can move the map. How can I have the search bar on top of the map and also move the map.
I welcome alternative/better ways of doing what I'm trying to do.
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Dimensions
} from 'react-native';
import MapView from 'react-native-maps';
var {GooglePlacesAutocomplete} = require('react-native-google-places-autocomplete');
const homePlace = {description: 'Home', geometry: { location: { lat: 42.3969, lng: -71.1224 } }};
const workPlace = {description: 'Work', geometry: { location: { lat: 42.3, lng: -71.1 } }};
var screenWidth = Dimensions.get('window').width;
export default class myapp extends Component {
render() {
return (
<View style={styles.container}>
<MapView
style={styles.map}
initialRegion={{
latitude: 42.3967,
longitude: -71.1223,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}>
<MapView.Marker
coordinate={{
latitude: 42.3967,
longitude: -71.1223
}}/>
</MapView>
<GooglePlacesAutocomplete
placeholder='Search location'
minLength={2}
autoFocus={false}
autoCorrect={false}
listViewDisplayed='auto' // true/false/undefined
fetchDetails={true}
renderDescription={(row) => row.description} // custom description render
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
console.log(data)
console.log(details)
}}
getDefaultValue={() => {
return ''; // text input default value
}}
query={{
// available options: https://developers.google.com/places/web-service/autocomplete
key: 'AIzaSyAUYfbKtctkIibOgFnNN2x9Xg9i0sVxlhQ',
language: 'en',
types: 'geocode'
}}
styles={{
description: {
fontWeight: 'bold',
},
predefinedPlacesDescription: {
color: '#1faadb',
},
textInputContainer: {
backgroundColor: 'rgba(0,0,0,0)',
top: 15,
width: screenWidth-10,
borderWidth: 0
},
textInput: {
marginLeft: 0,
marginRight: 0,
height: 38,
color: '#5d5d5d',
fontSize: 16,
borderWidth: 0
},
listView: {
backgroundColor: 'rgba(192,192,192,0.9)',
top: 23
}
}}
currentLocation={true}
currentLocationLabel="Current location"
nearbyPlacesAPI='GooglePlacesSearch'
GoogleReverseGeocodingQuery={{
// available options for GoogleReverseGeocoding API : https://developers.google.com/maps/documentation/geocoding/intro
}}
GooglePlacesSearchQuery={{
// available options for GooglePlacesSearch API : https://developers.google.com/places/web-service/search
rankby: 'distance',
types: 'food'
}}
filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3', 'sublocality', 'administrative_area_level_2', 'administrative_area_level_1']}
// filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities
predefinedPlaces={[homePlace, workPlace]}
debounce={200}
//renderLeftButton={() => <Image source={require('left-icon')} />}
renderLeftButton={() => <Text></Text> }
renderRightButton={() => <Text></Text> }
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
map: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('myapp', () => myapp);

Add position styles to the react-native-google-places-autocomplete style property:
styles={{
container:{
position: 'absolute',
top: 0
},
description: {
fontWeight: 'bold',
},
.....

Related

Custom map marker showing on android device but not on iOS

I'm building a cross-platform app in React Native Expo, and am using react-native-maps to render a map with custom markers. I'm using the 'icon' prop on the Marker component to render a png image, and in addition to this, the Marker displays a child Text element, as follows:
<Marker
key={i}
coordinate={{
latitude: gig.location.latitude,
longitude: gig.location.longitude,
}}
icon={require('../assets/map-pin-50pc.png')}
onPress={() => {
navigation.navigate("GigDetails", {
venue: gig.venue,
gigName: gig.gigName,
image: gig.image,
blurb: gig.blurb,
isFree: gig.isFree,
genre: gig.genre,
dateAndTime: { ...gig.dateAndTime },
tickets: gig.tickets,
});
}}
>
<Text style={styles.gigInfo_text}>{gig.genre}</Text>
</Marker>
On android devices, the custom marker image and the text are rendered as expected. On iOS devices however, only the text is rendered, and the 'icon' image cannot be seen. Any suggestions as to why?
I tried importing the image and passing it to the icon prop as follows:
import mapPinImage from '../assets/map-pin-50pc.png'
...
...
icon = {mapPinImage}
This didn't work either. I also checked the size of the image which was 41x62 pixels, with a size of 2.41kb - well below apple's maximum size requirements.
For context, here's the entire component that render the map:
import { FC } from "react";
import { useState, useMemo } from "react";
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
Platform,
Dimensions
} from "react-native";
import MapView from "react-native-maps";
import { Marker } from "react-native-maps";
import { mapStyle } from "../util/mapStyle";
import { useGigs } from "../hooks/useGigs";
import { AntDesign } from "#expo/vector-icons";
import { format } from "date-fns";
import { mapProps } from "../routes/homeStack";
import { Switch } from 'react-native-paper'
import mapPinImage from '../assets/map-pin-50pc.png'
type MapScreenNavgationProp = mapProps['navigation']
interface Props {
navigation: MapScreenNavgationProp
}
const GigMap:FC<Props> = ({ navigation }):JSX.Element => {
const [selectedDateMs, setSelectedDateMs] = useState<number>(Date.now());
const [isSwitchOn, setIsSwitchOn] = useState(false);
const gigs = useGigs();
//generates current date in format DD/MM/YYYY
const selectedDateString:string = useMemo(() => {
const formattedDate = format(new Date(selectedDateMs),'EEE LLL do Y')
return formattedDate
}, [selectedDateMs]);
const currentDay:string = useMemo(() => {
const formattedDay = format(new Date(selectedDateMs),'EEEE')
return formattedDay
},[selectedDateMs])
const currentWeek:string = useMemo(() => {
const formattedDay = format(new Date(selectedDateMs),'LLLL do Y')
return formattedDay
},[selectedDateMs])
//Filtering through gigs to return only current day's gigs
const gigsToday = gigs.filter((gig) => {
const formattedGigDate = format(new Date(gig.dateAndTime.seconds * 1000), 'EEE LLL do Y')
return formattedGigDate === selectedDateString;
});
const freeGigsToday = gigsToday.filter((gig) => {
return gig.isFree === true
})
const gigsToDisplay = isSwitchOn ? freeGigsToday : gigsToday
//increments date by amount
const addDays = (amount:number):void => {
setSelectedDateMs((curr) => curr + 1000 * 60 * 60 * 24 * amount);
};
const onToggleSwitch = () => setIsSwitchOn(!isSwitchOn);
return (
<View style={styles.container}>
<View testID="gigMapHeader" style={styles.headerText}>
<Text style={styles.headerText_main}>{currentDay}</Text>
<Text style={styles.headerText_sub}>{currentWeek}</Text>
</View>
<View style={styles.imageText}>
<Text style={styles.subHeader}>Tap on the</Text>
<Image
style={styles.image}
source={require("../assets/map-pin-new.png")}
/>
<Text style={styles.subHeader}>
icons on the map to see more gig info
</Text>
</View>
<View style={styles.mapContainer}>
<MapView
initialRegion={{
latitude: -41.29416,
longitude: 174.77782,
latitudeDelta: 0.03,
longitudeDelta: 0.03,
}}
style={styles.map}
customMapStyle={mapStyle}
>
{gigsToDisplay.map((gig, i) => {
return (
<Marker
key={i}
coordinate={{
latitude: gig.location.latitude,
longitude: gig.location.longitude,
}}
icon={require('../assets/map-pin-50pc.png')}
onPress={() => {
navigation.navigate("GigDetails", {
venue: gig.venue,
gigName: gig.gigName,
image: gig.image,
blurb: gig.blurb,
isFree: gig.isFree,
genre: gig.genre,
dateAndTime: { ...gig.dateAndTime },
tickets: gig.tickets,
});
}}
>
<Text style={styles.gigInfo_text}>{gig.genre}</Text>
</Marker>
);
})}
</MapView>
</View>
<View style={styles.buttonOptions}>
<TouchableOpacity onPress={() => addDays(-1)} style={styles.touchable}>
<AntDesign name="caretleft" size={36} color="#000000" />
<Text style={{ fontFamily: "NunitoSans", color: "#000000",marginLeft:'8%' }}>
Previous day
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => addDays(1)} style={styles.touchable}>
<AntDesign name="caretright" size={36} color="#000000" />
<Text style={{ fontFamily: "NunitoSans", color: "#000000",marginRight:'8%' }}>
Next day
</Text>
</TouchableOpacity>
</View>
<View style = {styles.buttonAndSwitch}>
<TouchableOpacity
onPress={() => navigation.navigate("List")}
style={styles.button}
>
<Text style={styles.buttonText}>List View</Text>
</TouchableOpacity>
<View style = {styles.switch}>
<Switch value={isSwitchOn} onValueChange={onToggleSwitch} color = '#377D8A' />
<Text style = {styles.switch_text}>Free Events</Text>
</View>
</View>
</View>
);
};
const {width:screenWidth, height:screenHeight} = Dimensions.get('window')
const mapWidth = screenWidth * 0.9 //this sets width to 90%
const mapHeight = mapWidth /0.91 //this set height based on the figma map aspect ratio of 0.91
const styles = StyleSheet.create({
container: {
// flexDirection: "column",
// alignItems: "center",
flex:1
},
map: {
height: '100%',
width: '100%'
},
mapContainer:{
marginTop: '5%',
marginHorizontal: 20,
width: mapWidth,
height: mapHeight,
flex:1,
...Platform.select({
ios: {
borderRadius:26,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.3,
shadowRadius: 2,
},
android: {
overflow: 'hidden',
borderRadius:26,
elevation: 4,
}
})
},
gigInfo: {
// backgroundColor: '#68912b',
// marginTop:20
},
gigInfo_text: {
fontSize:10,
color:'black',
fontFamily:'NunitoSans',
paddingTop: 25,
textAlign:'center',
fontWeight:'bold'
},
gigInfo_text_genre: {
color: "white",
fontFamily: "Helvetica-Neue",
transform: [{ translateY: -5 }],
},
headerText: {
color: "black",
fontSize: 25,
marginTop: '0%',
marginLeft: '7%',
fontFamily: "NunitoSans",
marginBottom: 10,
},
headerText_main: {
fontFamily: "NunitoSans",
fontSize:25,
lineHeight:34.1
},
headerText_sub: {
fontFamily:'LatoRegular',
size:14,
lineHeight:16.8
},
callout: {
width: "auto",
height: "auto",
backgroundColor: "azure",
},
buttonOptions: {
flexDirection: "row",
justifyContent: "space-between",
marginTop:'4%',
width:'100%'
},
buttonOptionsText: {
margin: 5,
},
image: {
height:20,
width:14,
marginHorizontal:3
},
imageText: {
flexDirection: "row",
marginLeft:'7%',
marginTop:27
},
touchable: {
flexDirection: "column",
alignItems: "center",
},
subHeader: {
fontFamily: "LatoRegular",
color: "#747474",
size: 12,
lineHeight: 17.04
},
button:{
flexDirection:'column',
width:115,
height:37,
marginLeft:'7%',
backgroundColor:'#377D8A',
borderRadius:8,
justifyContent:'center',
marginTop:'6%'
},
buttonText: {
color:'#FFFFFF',
textAlign:'center',
fontFamily: 'NunitoSans',
fontSize:16,
lineHeight:22
},
buttonAndSwitch:{
flexDirection:'row',
alignItems:'center',
justifyContent:'space-between'
},
switch:{
marginRight:'6%',
transform: [{translateY:7}]
},
switch_text: {
fontFamily: 'LatoRegular',
fontSize:10,
transform:[{translateY:-10}]
}
});
export default GigMap;
Try to replace icon image data props with image Icon as child component to Marker.
<Marker
key={i}
coordinate={{
latitude: gig.location.latitude,
longitude: gig.location.longitude,
}}
icon={require("../assets/map-pin-50pc.png")}
onPress={() => {
navigation.navigate("GigDetails", {
venue: gig.venue,
gigName: gig.gigName,
image: gig.image,
blurb: gig.blurb,
isFree: gig.isFree,
genre: gig.genre,
dateAndTime: { ...gig.dateAndTime },
tickets: gig.tickets,
});
}}
>
<Image
source={require("../assets/map-pin-50pc.png")}
style={{ width: 40, height: 40 }}
/>
<Callout>
<Text style={styles.gigInfo_text}>{gig.genre}</Text>
</Callout>
</Marker>

Add tabs into a React Native Maps

I want to add tabs at the bottom of my home screen but I don't manage how to do it.
I want two tabs like "Map" (for my homepage) and "Settings". I don't know how to create that, I tried to add some codes inside but it's not working. Do you have ideas of what I'm doing wrong?
Do I need to add these codes inside ?
class HomeScreen extends React.Component {
render() {
return (
class SettingsScreen extends React.Component {
render() {
return (
I also tried to add this code at the bottom:
const TabNavigator = createBottomTabNavigator({
MAP: { screen: HomeScreen },
SETTINGS: { screen: SettingsScreen },
});
export default createAppContainer(TabNavigator);
Here is my code:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Animated, Image, Dimensions } from "react-native";
import { Components, MapView } from 'expo';
const Images = [
{ uri: "https://images.unsplash.com/photo-1555706655-6dd427c11735?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80" },
{ uri: "https://images.unsplash.com/photo-1555706741-8f39aa887cf7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80" },
{ uri: "https://images.unsplash.com/photo-1555706741-fade7dd756a9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80" },
{ uri: "https://images.unsplash.com/photo-1555706742-67a1170e528d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80" }
]
const { width, height } = Dimensions.get("window");
const CARD_HEIGHT = height / 5;
const CARD_WIDTH = CARD_HEIGHT - 50;
export default class screens extends Component {
state = {
markers: [
{
coordinate: {
latitude: 41.414494,
longitude: 2.152695,
},
title: "Parc Güell",
description: "One of the best view in Barcelona. ",
image: Images[0],
},
{
coordinate: {
latitude: 41.403706,
longitude: 2.173504,
},
title: "Sagrada Familia",
description: "This is the second best place in Portland",
image: Images[1],
},
{
coordinate: {
latitude: 41.395382,
longitude: 2.161961,
},
title: "Casa Milà",
description: "This is the third best place in Portland",
image: Images[2],
},
{
coordinate: {
latitude: 41.381905,
longitude: 2.178185,
},
title: "Gothic Quarter",
description: "This is the fourth best place in Portland",
image: Images[3],
},
],
region: {
latitude: 41.390200,
longitude: 2.154007,
latitudeDelta: 0.04864195044303443,
longitudeDelta: 0.040142817690068,
},
};
componentWillMount() {
this.index = 0;
this.animation = new Animated.Value(0);
}
componentDidMount() {
// We should detect when scrolling has stopped then animate
// We should just debounce the event listener here
this.animation.addListener(({ value }) => {
let index = Math.floor(value / CARD_WIDTH + 0.3); // animate 30% away from landing on the next item
if (index >= this.state.markers.length) {
index = this.state.markers.length - 1;
}
if (index <= 0) {
index = 0;
}
clearTimeout(this.regionTimeout);
this.regionTimeout = setTimeout(() => {
if (this.index !== index) {
this.index = index;
const { coordinate } = this.state.markers[index];
this.map.animateToRegion(
{
...coordinate,
latitudeDelta: this.state.region.latitudeDelta,
longitudeDelta: this.state.region.longitudeDelta,
},
350
);
}
}, 10);
});
}
render() {
const interpolations = this.state.markers.map((marker, index) => {
const inputRange = [
(index - 1) * CARD_WIDTH,
index * CARD_WIDTH,
((index + 1) * CARD_WIDTH),
];
const scale = this.animation.interpolate({
inputRange,
outputRange: [1, 2.5, 1],
extrapolate: "clamp",
});
const opacity = this.animation.interpolate({
inputRange,
outputRange: [0.35, 1, 0.35],
extrapolate: "clamp",
});
return { scale, opacity };
});
return (
<View style={styles.container}>
<MapView
ref={map => this.map = map}
initialRegion={this.state.region}
style={styles.container}
>
{this.state.markers.map((marker, index) => {
const scaleStyle = {
transform: [
{
scale: interpolations[index].scale,
},
],
};
const opacityStyle = {
opacity: interpolations[index].opacity,
};
return (
<MapView.Marker key={index} coordinate={marker.coordinate}>
<Animated.View style={[styles.markerWrap, opacityStyle]}>
<Animated.View style={[styles.ring, scaleStyle]} />
<View style={styles.marker} />
</Animated.View>
</MapView.Marker>
);
})}
</MapView>
<Animated.ScrollView
horizontal
scrollEventThrottle={1}
showsHorizontalScrollIndicator={false}
snapToInterval={CARD_WIDTH}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: this.animation,
},
},
},
],
{ useNativeDriver: true }
)}
style={styles.scrollView}
contentContainerStyle={styles.endPadding}
>
{this.state.markers.map((marker, index) => (
<View style={styles.card} key={index}>
<Image
source={marker.image}
style={styles.cardImage}
resizeMode="cover"
/>
<View style={styles.textContent}>
<Text numberOfLines={1} style={styles.cardtitle}>{marker.title}</Text>
<Text numberOfLines={1} style={styles.cardDescription}>
{marker.description}
</Text>
</View>
</View>
))}
</Animated.ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollView: {
position: "absolute",
bottom: 30,
left: 0,
right: 0,
paddingVertical: 10,
},
endPadding: {
paddingRight: width - CARD_WIDTH,
},
card: {
padding: 10,
elevation: 2,
backgroundColor: "#FFF",
marginHorizontal: 10,
shadowColor: "#000",
shadowRadius: 5,
shadowOpacity: 0.3,
shadowOffset: { x: 2, y: -2 },
height: CARD_HEIGHT,
width: CARD_WIDTH,
overflow: "hidden",
},
cardImage: {
flex: 3,
width: "100%",
height: "100%",
alignSelf: "center",
},
textContent: {
flex: 1,
},
cardtitle: {
fontSize: 12,
marginTop: 5,
fontWeight: "bold",
},
cardDescription: {
fontSize: 12,
color: "#444",
},
markerWrap: {
alignItems: "center",
justifyContent: "center",
},
marker: {
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: "rgba(130,4,150, 0.9)",
},
ring: {
width: 24,
height: 24,
borderRadius: 12,
backgroundColor: "rgba(130,4,150, 0.3)",
position: "absolute",
borderWidth: 1,
borderColor: "rgba(130,4,150, 0.5)",
},
});
create a new file for tab navigation and add the following code:
(I imported your map component as screens)
import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import TabBarIcon from '../components/TabBarIcon';
import screens from '../screens/HomeScreen';
import SettingsScreen from '../screens/SettingsScreen';
const HomeStack = createStackNavigator({
Home: screens,
});
HomeStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-information-circle${focused ? '' : '-outline'}`
: 'md-information-circle'
}
/>
),
};
const SettingsStack = createStackNavigator({
Settings: SettingsScreen,
});
SettingsStack.navigationOptions = {
tabBarLabel: 'Settings',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? 'ios-options' : 'md-options'}
/>
),
};
export default createBottomTabNavigator({
HomeStack,
SettingsStack,
});

Error: "Invalid data message - all must be length: 8" - PickerIOS

Edit: it seems that if I comment out the line "this.setState({logged_in: true});", line 63, that I don't get the error. My guess is that something about the way I'm trying to change the content being displayed in the render function based on if the user is logged in or not is what is the cause of this error. Any ideas?
I've been making some slight progress in understanding some very basics of React Native, I feel like. Although my code might not be pretty, up until some recent additions it worked. I'm recieving an error message in the IOS Simulator that reads "Invalid data message - all must be length: 8". It unfortunately isn't giving me any specifics that I understand, such as linenumbers.
I sincerely apologise if this is a repost, I've been looking like crazy on google and stackoverflow to find a solution to this error but have been unsuccessful in my searches.
I've censored the url I've using in fetch since it is an adress for testing within the company in very early stages, but I am 99,99% sure that's not where the problem lies.
My index.ios.js:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button,
Alert,
TextInput,
TouchableHighlight,
Image,
AlertIOS,
PickerIOS,
} from 'react-native';
var REASONS = {
sick: {
name: "sjuk"
},
vacation: {
name: "semester"
},
child_care: {
name: "vård av barn"
},
parenting: {
name: "föräldraledig"
},
general: {
name: "övrigt"
},
};
export default class mbab_franvaro extends Component {
constructor(props) {
super(props);
this.state = {username: '', password: '', logged_in: false, reason: 'sjuk'};
}
logout(){
this.setState({logged_in: false});
this.username = ""; this.password = "";
}
login(){
if(this.state.username == "" || this.state.password == ""){
AlertIOS.alert("Fel", "Vänligen fyll i alla fält.");
}
else{
fetch("MY_PRIVATAE_COMPANY_URL", {
method: "POST",
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: "username=" + this.state.username + "&password=" + this.state.password,
})
.then((response) => response.json())
.then((response) => {
if(JSON.stringify(response.body).replace(new RegExp('"', 'g'), '').match("Inloggad")){
this.username = this.state.username; this.password = this.state.password;
this.setState({logged_in: true});
//AlertIOS.alert("Hej!", "Välkommen " + this.username + "!");
}
else{
AlertIOS.alert(
"Fel",
JSON.stringify(response.body).replace(new RegExp('"', 'g'), '')
);
}
})
.catch((error) => {
AlertIOS.alert("error", error);
})
.done();
}
}
render(){
if(this.state.logged_in){
//sidan för frånvarorapportering
return (
<View style={styles.container}>
/*<TouchableHighlight style={styles.logout_button} onPress={() => this.logout()}>
<Text style={styles.login_button_text}>Logga ut</Text>
</TouchableHighlight>*/
<View style={styles.report_wrapper}>
<Text style={styles.header}>Frånvarorapportering</Text>
<Text>Ange anledning och hur stor del av dagen du blir frånvarande.</Text>
<PickerIOS
selectedValue={this.state.reason}
onValueChange={(reason) => this.setState({reason})}>
{Object.keys(REASONS).map((reason) => (
<PickerItemIOS
key={reason}
value={reason}
label={REASONS[reason].name}
/>
))}
</PickerIOS>
</View>
</View>
);
}
else{
//inloggningssidan
return (
<View style={styles.container}>
<Image resizeMode="center" style={styles.logo} source={require('./app/res/logo_cmyk.png')} />
<TextInput
placeholder="Namn"
autocorrect={false}
style={styles.text_box}
onChangeText={(username) => this.setState({username})}
/>
<TextInput
placeholder="Lösenord"
autocorrect={false}
secureTextEntry={true}
style={styles.text_box}
onChangeText={(password) => {this.setState({password})}}
/>
<TouchableHighlight style={styles.login_button} onPress={() => this.login()}>
<Text style={styles.login_button_text}>Logga in</Text>
</TouchableHighlight>
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F4F4F4',
},
report_wrapper: {
flex: 1,
},
logout_button: {
flex: 0,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginLeft: 10,
marginRight: 10,
marginTop: 30,
marginBottom: 2,
padding: 10,
backgroundColor: "#003878"
},
login_button: {
flex: 0,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginLeft: 10,
marginRight: 10,
marginTop: 2,
marginBottom: 2,
padding: 10,
backgroundColor: "#003878"
},
login_button_text: {
color: "white",
fontSize: 20,
flex: 1,
textAlign: "center",
},
logo: {
//flex: 1,
},
text_box: {
height: 40,
flex: 0,
backgroundColor: "white",
marginLeft: 10,
marginRight: 10,
marginTop: 2,
marginBottom: 2,
padding: 10
},
header: {
color: "#84754E",
fontSize: 25,
marginTop: 30,
},
});
AppRegistry.registerComponent('mbab_franvaro', () => mbab_franvaro);
Edit:
Add toString() to error did the trick for me:
.catch((error) => {
AlertIOS.alert("error", error.toString());
})
I was also getting the same error while using ScrollView.
Took me 2 days to figure out the solution.
I wasn't importing ScrollView from react-native.
Check if you've imported the Picker or not. :)

left side of screen untouchable when using NavigatorIOS react-native

I have this very strange bug on my react-native iOS app, when I'm using NavigatorIOS (need it) : there is a 30 points zone on the left of the screen that is not touchable on the first touch (nothing happens on touchableHighlight or TouchableWithoutFeedback) in Listview elements for example...
When I use Navigator, no problem at all, it's specific to NavigatorIOS (and I need it in this part of the app), also tried without any style, same problem.
Haven't seen any github issue or discussion about this bug.
Edit :
Runnable example : https://rnplay.org/apps/E0R2vg
Component code sample:
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
NavigatorIOS,
ListView,
TouchableWithoutFeedback,
Dimensions,
} = React;
var myListView = React.createClass({
getInitialState: function() {
return {
ds: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
};
},
componentDidMount: function() {
console.log('feed datasource');
this.setState({
ds: this.state.ds.cloneWithRows([{name: 'one'}, {name:'two'}, {name: 'three'}]),
});
},
render: function() {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.ds}
renderRow={this.renderItem}
style={styles.listView}
/>
<TouchableWithoutFeedback onPress={this.nextroute}>
<View style={[styles.pressme, {flex:1}]}>
<Text>Next route to see the issue</Text>
</View>
</TouchableWithoutFeedback>
</View>
);
},
renderItem: function(item) {
return (
<View style={styles.row}>
<TouchableWithoutFeedback onPress={() => alert('pressed')}>
<View style={styles.pressme}>
<Text>x</Text>
</View>
</TouchableWithoutFeedback>
<Text>{item.name} - Item description...</Text>
</View>
);
},
nextroute: function() {
this.props.navigator.push({
title: 'Try press [x] (twice)',
component: myListView,
onLeftButtonPress: () => this.props.navigator.pop(),
});
},
});
var SampleApp = React.createClass({
render: function() {
return (
<NavigatorIOS
style={styles.navcontainer}
initialRoute={{
component: myListView,
title: 'First view is ok',
}}
tintColor="#000000"
barTintColor="#fd7672"
translucent={false}
ref='navios'
/>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 28,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
fontSize: 19,
marginBottom: 5,
},
navcontainer: {
flex: 1,
},
listView: {
flex: 1,
width: Dimensions.get('window').width,
},
row: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: '#FFFFFF',
},
pressme: {
margin: 10,
borderWidth: 1,
borderColor: 'red',
padding: 15,
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);

React Native Image URI Not Showing

While rendering a set of row components in ListView, my uri images seem not to be showing up at all. I have included Image in the react module. My custom component is the following:
var url = rowData.mediaGroups[0].contents[0].url;
if (url.indexOf('w=150') > -1)
{
url.replace("w=150", "w=500");
}
return <ArticlePreview
category={rowData.categories[0]}
key={sectionID}
heartText={'2.9k'}
categoryPress={this.onCategoryDetailsPress}
selected={false}
source={{ uri: url }}
text={rowData.title.toLowerCase().replace(' ','')}
onPress={this.onArticleDetailsPress} />
The component has multiple properties and is used throughout my app (and works there with link images). But for some reason the component just stopped working in the app for uri images. Not sure what to do. Here is the code for the component itself:
//component for article preview touchable image
/* will require the following
- rss feed and api
- user's keyword interests from parse In home.js
- parse db needs to be augmented to include what they heart
- parse db needs to be augmented to include what they press on (like google news)
*/
var React = require('react-native');
var {
View,
StyleSheet,
Text,
Image,
TouchableHighlight,
} = React;
//dimensions
var Dimensions = require('Dimensions');
var window = Dimensions.get('window');
var ImageButton = require('../../common/imageButton');
var KeywordBox = require('../../authentication/onboarding/keyword-box');
//additional libraries
module.exports = React.createClass({
//onPress function that triggers when button pressed
//this.props.text is property that can be dynamically filled within button
/* following props:
- source={this.props.source}
- onPress={this.props.onPress}
- {this.props.text}
- {this.props.heartText}
- key={this.props.key}
- text={this.props.category}
- this.props.selected
*/
render: function() {
return (
<TouchableHighlight
underlayColor={'transparent'}
onPress={this.props.onPress} >
<Image source={this.props.source} style={[styles.articlePreview, this.border('red')]}>
<View style={[styles.container, this.border('organge')]}>
<View style={[styles.header, this.border('blue')]}>
<Text style={[styles.previewText]}>{this.props.text}</Text>
</View>
<View style={[styles.footer, this.border('white')]}>
<View style={[styles.heartRow, this.border('black')]}>
<ImageButton
style={[styles.heartBtn, , this.border('red')]}
resizeMode={'contain'}
onPress={this.onHeartPress}
source={require('../../img/heart_btn.png')} />
<Text style={[styles.heartText]}>{this.props.heartText} favorites</Text>
</View>
<KeywordBox
style={[styles.category, this.border('blue')]}
key={this.props.key}
text={this.props.category}
onPress={this.props.categoryPress}
selected={this.props.selected} />
</View>
</View>
</Image>
</TouchableHighlight>
);
},
onHeartPress: function() {
//will move this function to a general module
},
border: function(color) {
return {
//borderColor: color,
//borderWidth: 4,
}
},
});
var styles = StyleSheet.create({
heartText: {
color: 'white',
fontSize: 12,
fontWeight: 'bold',
alignSelf: 'center',
marginLeft: 5,
},
heartRow: {
flexDirection: 'row',
justifyContent: 'space-around',
alignSelf: 'center',
justifyContent: 'center',
},
heartBtn: {
height: (92/97)*(window.width/13),
width: window.width/13,
alignSelf:'center',
},
category: {
fontFamily: 'Bebas Neue',
fontSize: 10,
fontWeight: 'bold'
},
header: {
flex: 3,
alignItems: 'center',
justifyContent: 'space-around',
marginTop: window.height/30,
},
footer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
margin: window.height/50,
},
container: {
flex: 1,
backgroundColor: 'black',
opacity: 0.6,
},
articlePreview: {
flex: 1,
height: window.height/3.2,
width: window.width,
flexDirection: 'column'
},
previewText: {
fontFamily: 'Bebas Neue',
fontSize: 23,
color: 'white',
alignSelf: 'center',
textAlign: 'center',
margin: 5,
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0
},
});
The UI currently looks like this with not images (has black background):
Checked my rss feeds - some were unreliable resulting in messing with the way the images were being shown

Resources