I want to add some more information on the bottom of the page and fix this bottom card portion on this page.But on scrolling i want to view the other informations i want to add at the bottom which will only be shown after scrolling.How can i do that?
I am having this code for now:
render(){
return(
<View style={styles.container}>
<MapView style={styles.mapcontainer}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}} />
<JobInfo/>
</View>
)
}
}
const styles = StyleSheet.create ({
container: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
justifyContent: 'flex-end',
alignItems: 'center'
},
mapcontainer: {
flex: 1,
width: width,
height: height
}
})
class JobInfo extends Component {
render() {
return (
<View style={{width: '100%'}}>
<Card>
<CardItem >
<Text>General Info:</Text>
</CardItem>
<CardItem >
<Body>
<Text>
Click on any carditem
</Text>
</Body>
</CardItem>
<CardItem >
<Text>Packaging Info:</Text>
</CardItem>
<CardItem >
<Body>
<Text>
Click on any carditem
</Text>
</Body>
</CardItem>
<CardItem >
<Text>Manpower Info:</Text>
</CardItem>
<CardItem >
<Body>
<Text>
Click on any carditem
</Text>
</Body>
</CardItem>
</Card>
</View>
)
}
}
ScrollView is somehow not working.Any help would be appreciated.Thanks.
try below method
add JobInfo into a Scrollview . and remove height prop from mapContainer
<ScrollView style={[{flex:1} ,{ width: '100%'}, {justifyContent: 'flex-start'}]}>
<JobInfo/>
</ScrollView>
And mapContainer is
mapcontainer: {
flex: 3,
width: '100%',
}
Use flex values to adjust height of the map
Edit 1
If you want scroll all container (both Map & JobInfo ) you need to set specific height for Map. Wrap all elements to a single ScrollView like below
<ScrollView style={[{flex:1} , {justifyContent: 'flex-start'}]}>
<View style={styles.container}>
<MapView style={styles.mapcontainer}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}} />
<JobInfo/>
</View>
</ScrollView>
And styles are follows
const styles = StyleSheet.create ({
container: {
flex: 1,
},
mapcontainer: {
width: '100%',
height:600,
}
})
Related
I am building a react native application and I use scrollview for some contents but it is not scrolling I cannot figure out why.
I try a lot of things, adding flex: 1 everywhere but none of these is working.
Thank you in advance for your help.
<KeyboardAwareScrollView contentContainerStyle={authStyles.container}>
<Layout isBackArrow={true}>
<BottomLayout>
<Header fontSize={20}>
<Text>Nous sommes</Text> {'\n'}
<Text style={authStyles.headerBold}>
Ravis de te revoir!
</Text>
{'\n'}
<Caption>Je me connecte via:</Caption>
</Header>
<View style={authStyles.socialIconView}>
<SocialIcon type="facebook" onPress={onFacebookLogin} />
<SocialIcon type="google" />
<SocialIcon
type="apple"
onPress={onAppleButtonPress}
style={{ backgroundColor: COLORS.BLACK }}
/>
</View>
<View style={authStyles.orView}>
<Header fontSize={15}>
<Text style={authStyles.headerBold}>Ou</Text>
{'\n'}
<Caption>
Je saisis mon email et mot de passe
</Caption>
</Header>
</View>
<View style={authStyles.inputView}>
<CustomInput
label="Email"
icon
iconName="envelope"
iconFamily="font-awesome"
onChange={text => setEmail(text)}
/>
<CustomInput
label="Mot de passe"
icon
iconName="lock"
iconFamily="entypo"
onChange={text => setPassword(text)}
password
/>
<CustomButton
title="Mot de passe oubliƩ ?"
clear
onPress={open}
/>
</View>
</BottomLayout>
</Layout>
</KeyboardAwareScrollView>
Layout component:
<View style={layoutStyles.background}>
{isBackArrow && <BackArrow onPress={onBackArrowPress} />}
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={{
flex: 1,
}}
>
{children}
</ScrollView>
</View>
layout style:
background: {
backgroundColor: COLORS.BRAND_ORANGE_OPACITY_2,
width: '100%',
height: '100%',
flex: 1,
},
BottomLayout Component:
<View style={layoutStyles.bottomLayout}>{children}</View>;
bottom layout style:
bottomLayout: {
backgroundColor: COLORS.BRAND_ORANGE,
position: 'absolute',
bottom: 0,
height: '75%',
width: '100%',
borderTopLeftRadius: 70,
borderTopRightRadius: 70,
paddingTop: 60,
flex: 1,
},
keyboardAwareScrollView contentContainerStyle:
container: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
},
Thanks in advance.
KeyboardAwareScrollView gives you a ScrollView already, you don't need to add another one inside of it.
Remove the ScrollView from Layout or remove the KeyboardAwareScrollView.
React Native Nested ScrollView Can`t Scroll on Android Device
Also don't use flex: 1 in contentContainerStyle, instead use minHeight: '100%' (why?) if you want it to be full screen even when there is not enough content in it.
I am trying to create a Swiggy/Zomato/FoodPanda like the app, I am trying to get user location or set delivery location on to the map.
The issue is happening on Android.
But I am not experiencing a smoothness when moving marker position, especially when zooming in and zooming out.
Map glitches when trying to move pin marker position
please suggest me for improvement and for to get smoothness experience.
I am trying a lot of logic but not getting any desired performance.
Here is my implemented code,
This is my initial setup on constructor
constructor(props) {
super(props);
this.latDelta = 0.00922 * 1.5;
this.longDelta = 0.00421 * 1.5;
this.state = {
visible: false,
address: {},
lastLat: 24.8076793,
lastLong: 93.9360916,
mapRegion: new AnimatedRegion({
latitude: 24.8076793,
longitude: 93.9360916,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta
}),
marker: null,
region: new AnimatedRegion({
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
latitude: 24.8076793,
longitude: 93.9360916
}),
autoGeoMarker: {
latitude: 24.8076793,
longitude: 93.9360916,
autoMapAddress: '',
autoMapArea: ''
},
setGeoMarker: {
latitude: 24.8076793,
longitude: 93.9360916,
setMapAddress: '',
setMapArea: ''
},
mapIndicator: false,
mapAddress: '',
mapArea: '',
//-----
indicator: true,
searchModal: false
};
}
componentDidMount() {
this.getPermissionLocation();
}
Here I am asking for permission
getPermissionLocation = () => {
try {
request(
Platform.select({
android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
})
).then(res => {
if (res == 'granted') {
this.setState({
searchModal: false
});
Geolocation.getCurrentPosition(
//Will give you the current location
position => {
let region = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta
};
Alert.alert('', 'Pin Your Delivery point by moving map');
this.setState({
autoGeoMarker: region,
mapIndicator: false,
indicator: false
});
this.onRegionChange(region);
this.getAutoDetectAddress(region.latitude, region.longitude);
},
error => {
//setLocationStatus(error.message);
console.log('error ... 1 ' + error.message);
},
{
enableHighAccuracy: false,
timeout: 30000,
maximumAge: 1000
}
);
} else {
console.log('Location is not enabled');
Alert.alert(
'Enable Your Location:',
'Can not proceed, Please allow your Location permissioin.',
[{ text: 'OK', onPress: () => RNRestart.Restart() }]
);
}
});
} catch (error) {
console.log('location set error:', error);
}
};
//Get Auto Geolocation address
getAutoDetectAddress = (latitude, longitude) => {
Geocoder.from(latitude, longitude)
.then(json => {
let region = {
latitude: latitude,
longitude: longitude,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
autoMapAddress: json.results[0].formatted_address,
autoMapArea: json.results[0].address_components[1].short_name
};
this.setState({
autoGeoMarker: region
});
})
.catch(error => console.warn(error));
//-----------------------
};
onRegionChange = region => {
this.setState({
region: region,
lastLat: region.latitude,
lastLong: region.longitude
});
this.getAddressInfo(region.latitude, region.longitude);
};
getAddressInfo = (latitude, longitude) => {
Geocoder.from(latitude, longitude)
.then(json => {
this.setState({
mapAddress: json.results[0].formatted_address,
mapArea: json.results[0].address_components[1].short_name
});
let region = {
latitude: json.results[0].geometry.location.lat,
longitude: json.results[0].geometry.location.lng,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
setMapAddress: json.results[0].formatted_address,
setMapArea: json.results[0].address_components[1].short_name
};
this.setState({
setGeoMarker: region
});
})
.catch(error => console.warn(error));
};
render() {
return this.state.indicator ? (
<View style={{ flex: 1 }}>
<ActivityIndicator size="large" color="#ff6a00" />
</View>
) : (
<View style={{ flex: 1, flexDirection: 'column' }}>
<StatusBar backgroundColor="#ff6a00" />
<View style={styles.map}>
<MapView
style={styles.map}
region={this.state.region}
onRegionChangeComplete={this.onRegionChange}
/>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
position: 'absolute',
top: '4%',
left: '-3%'
}}
>
<TouchableOpacity
onPress={() => {
{
this.props.navigation.navigate('HomeScreen');
}
}}
>
<Image
style={{ width: 71, height: 51 }}
source={require('../../assets/app/mapback.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.markerFixed}>
<Image style={styles.marker} source={marker} />
</View>
</View>
<View
style={{
flex: 1,
padding: 4,
backgroundColor: '#FFFFFF'
// borderTopColor: 'black',
// borderTopWidth: 1
}}
>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginTop: 15,
marginLeft: 20
}}
>
<View
style={{ flex: 0.8, alignItems: 'center', flexDirection: 'row' }}
>
<Image
style={{ width: 15, height: 20 }}
source={require('../../assets/app/mapmark.png')}
/>
<Text
style={{
fontSize: 18,
marginLeft: 15,
fontFamily: 'Nunito-Black'
}}
>
{this.state.mapArea}
</Text>
</View>
</View>
<Text
style={{
marginTop: 20,
marginLeft: 20,
fontSize: 12,
fontFamily: 'Poppins-Regular'
}}
>
{this.state.mapAddress}
</Text>
</View>
</View>
);
}
here I have doubt where to set these two function properly
this.onRegionChange(region);
this.getAutoDetectAddress(region.latitude, region.longitude);
maybe if these two functions but I am not sure. Where to implement correctly for getting the best performance.
Map glitches or bouncing (While pinching/zooming in and out) issue were caused by using region={this.state.region}
So, I used initialRegion={this.state.region} instead of region
Here is the complete example
onChangeValue = region => {
this.setState({
region
});
Geocoder.from(region.latitude, region.longitude)
.then(json => {
this.setState({
mapAddress: json.results[0].formatted_address,
mapArea: json.results[0].address_components[1].short_name
});
let region = {
latitude: json.results[0].geometry.location.lat,
longitude: json.results[0].geometry.location.lng,
latitudeDelta: 0.021,
longitudeDelta: 0.021,
setMapAddress: json.results[0].formatted_address,
setMapArea: json.results[0].address_components[1].short_name
};
this.setState({
setGeoMarker: region
});
// this.map.animateToRegion(region);
})
.catch(error => console.warn(error));
};
...
<MapView
style={{
flex: 1,
height: Dimensions.get('screen').height / 1.5,
position: 'relative',
marginBottom: this.state.marginBottom
}}
showsUserLocation={true}
initialRegion={this.state.region}
// region={this.state.region}
showsMyLocationButton={true}
onRegionChangeComplete={this.onChangeValue}
ref={ref => (this.map = ref)}
/>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
position: 'absolute',
top: '4%',
left: '-3%'
}}
>
<TouchableOpacity
onPress={() => {
{
this.props.navigation.navigate('MainTabScreen');
this.props.navigation.navigate('HomeScreen');
}
}}
>
{/*<Icon.MaterialIcons name="arrow-back" size={28} color="black" />*/}
<Image
style={{ width: 71, height: 51 }}
source={require('../../assets/app/mapback.png')}
/>
</TouchableOpacity>
</View>
...
I am not able to display images (both from the assets and web) in custom marker callout : the image in callout is always shown as a blank rectangle.
class CustomCalloutView extends React.Component {
render() {
return (
<View>
<View>
<Text style={{
fontWeight: "bold",
}}>
Test
</Text>
</View>
<View>
<Image
source={{ uri: 'https://facebook.github.io/react/logo-og.png' }}
style={{ width: 100, height: 100 }}
/>
</View>
</View>
)
}
}
And the main Map component is:
<MapView
style={{ flex: 1 }}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}>
{this.state.markers.map(marker => (
<Marker
key={marker.id}
coordinate={marker.latlng}>
<Callout>
<CustomCalloutView />
</Callout>
</Marker>
))}
</MapView>);
The marker is correctly shown, and the callout renders, but the image is not shown. The same image works if i use it in a normal view.
I am using expo (expo.io) but also tried emulator and installed APK on the device (android; no info about ios).
Use Image inside Text component.
Something like this:
<Text>
<Image style={{ height: 100, width:100 }} source={{ ... }} resizeMode="cover" />
</Text>
Another workaround by using WebView.
I think is the proper solution for this right now.
<View>
<WebView style={{ height: 100 , width: 230, }} source={{ uri: ... }} />
</View>
Positioning the <Image/> was a bit challenge in the custom Callout for Android. It's a bit mystery for Android, IMHO. Especially, with the trick to display it by wrapping around Text. Looks like, it affects the styling, too. I've had to figure out monotonously the https://reactnative.dev/docs/image#resizemode with this "fix" along with some custom styling what works, pff.
I've ended up with 2 different styles, one for Android, one for iOS.
{Platform.OS === "android" ? <Text style={styles.imageWrapperAndroid}>
<Image
resizeMode="cover"
source={
event.imageUrl
? { uri: event.imageUrl }
: require("../assets/images/no-image.jpeg")
}
style={styles.imageAndroid}
/>
</Text> : <Image
source={
event.imageUrl
? { uri: event.imageUrl }
: require("../assets/images/no-image.jpeg")
}
style={styles.imageIOS}
/>}
...
const styles = StyleSheet.create({
imageAndroid: {
height: 200,
width: 330,
},
imageIOS: {
height: "50%",
width: "100%",
},
imageWrapperAndroid: {
height: 200,
flex: 1,
marginTop: -85,
width: 330,
},
...
});
I am trying to keep the marker centered on the map, while dragging the map around the marker, like how Uber does it, when a user is trying to choose a location. the below code work perfectly on IOS but the marker is getting hidden on Android I think, How can I solve this issue for Android?
<View style={styles.map}>
<MapView
region={this.getMapRegion()}
style={styles.map}
provider={PROVIDER_GOOGLE}
mapType="standard"
onRegionChangeComplete={(region) => this.setState({
atitude: region.latitude, longitude: region.longitude,
latitudeDelta: region.latitudeDelta, longitudeDelta: region.longitudeDelta
})} >
<View style={{
left: '50%',
marginLeft: -24,
marginTop: -48,
position: 'absolute',
top: '50%',}}>
<Image
style={{
resizeMode: 'contain',
height: 60, width: 60,
}} source={require('../../assets/fake-marker.png')} />
</View>
</MapView>
</View>
Your code should work fine on Android and IOS, you just made a simple mistake you wrapped up your custom marker inside the MapView, you just need to move it outside and everything will work like a charm.
i used something like that
<View style ={styles.container}>
<MapView
showsUserLocation
showsMyLocationButton
style={styles.map}
onRegionChangeComplete={this.onRegionChange.bind(this)}
region={this.state.region}
>
</MapView>
<View
style={{ flex:1,
flexDirection:'row',
alignItems:'center',
justifyContent:'center'}} pointerEvents="none">
<Image style={styles.marker} source=require("./../../assets/pic/my_loc.png")} />
</View>
</View>
and use this styles`
[![container: {
flex:1,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
marker: {
height: 48,
width: 48,
},`][1]][1]
I want to achieve a behavior like android's CoordinatorLayout enter always for my ToolBar i tried too many solutions some did work but not fully like https://github.com/maolion/mao-rn-android-kit which is really cool but with one setback as it doesn't work with ListView i also tried Animated but the scroll event throttle on android is just not working most of the times it does not even work.
Using mao-rn-android-kit
<CoordinatorLayoutAndroid ref={(component) => this.coordinatorLayout = component} fitsSystemWindows={false}>
<AppBarLayoutAndroid
layoutParams={{
width: 'match_parent',
height: 112
}}
style={{ backgroundColor:"#528eff" }}>
<View layoutParams={{height: 56, width: this.windowWidth, scrollFlags: (
AppBarLayoutAndroid.SCROLL_FLAG_SCROLL |
AppBarLayoutAndroid.SCROLL_FLAG_ENTRY_ALWAYS)}} style={{height: 56}}>
<ToolbarAndroid
titleColor={'#FFF'}
title={this.props.title}
navIcon={images.arrowBack}
onIconClicked={() => this._goBack()}
onActionSelected={() => {}}
actions={[{title: 'Search', icon: images.search, show: 'always'}]}
style={[{backgroundColor: '#528eff', width: this.windowWidth, height: 56}]}/>
</View>
<View layoutParams={{height: 56, width: this.windowWidth}}
style={{flex: 0, flexDirection: 'row', justifyContent: 'center', width: this.windowWidth, backgroundColor: '#528eff'}}>
<TouchableOpacity onPress={() => this.getDocuments('high')}
style={[styles.highNormalLowDocListHeaderStateTextContainer, highSelected.borderStyle]}>
<Text
style={[styles.highNormalLowDocListHeaderStateText, highSelected.textStyle]}>HIGH</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.getDocuments('normal')}
style={[styles.highNormalLowDocListHeaderStateTextContainer, normalSelected.borderStyle]}>
<Text
style={[styles.highNormalLowDocListHeaderStateText, normalSelected.textStyle]}>NORMAL</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.getDocuments('low')}
style={[styles.highNormalLowDocListHeaderStateTextContainer, lowSelected.borderStyle]}>
<Text
style={[styles.highNormalLowDocListHeaderStateText, lowSelected.textStyle]}>LOW</Text>
</TouchableOpacity>
</View>
</AppBarLayoutAndroid>
<View
ref={(component) => this.contentLayout = component}
style={{flex: 1, backgroundColor: 'transparent', height: this.windowHeight - 150}}>
<ListView
style={{height: this.windowHeight - 150, overflow: 'hidden'}}
dataSource={this.state.documents}
enableEmptySections={true}
renderRow={(rowData) => this._renderRow(rowData)}
/>
</View>
</CoordinatorLayoutAndroid>
The key to reacting to the scroll position fluidly is using Animated.event along with the onScroll to update an Animated.value
getInitialState: function() {
return {
scrollY: new Animated.Value(0)
}
},
render() {
return (
<ScrollView
scrollEventThrottle={16}
onScroll={Animated.event(
[{nativeEvent:
{contentOffset:
{y: this.state.scrollY}
}
}]
)}>
// etc ...
}
I could then call interpolate on this.state.scrollY and feed this value into a transform style on another component that I wanted to update as the ScrollView scrolled.