Related
I have built an animated search bar in react native just like search bar of facebook mobile application. The search bar opens up when the search button is clicked on the header. It currently takes same height as the custom header that it is being rendered on. But i want to increase the height of the header to half the screen size when the search bar is on focus and set the height to default when the search bar is not focused. I have tried using my own logic but the problem was when i increased the height the contents of headers were shown below the search bar. And i dont want that. Can anyone help me how to resolve this?
/* eslint-disable #typescript-eslint/no-unused-vars */
import React, {useContext, useRef} from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
SafeAreaView,
Animated,
TextInput,
Easing,
} from 'react-native';
import Logo from '#assets/images/NCLogo.png';
import Colors from '#constants/colors/colors';
import Search from '#assets/icons/Search.svg';
import Back from '#assets/icons/back-arrow.svg';
import {AuthContext} from '#components/ContextStore/AuthContext/AuthContext';
import DateAndDayGenerator from '#utils/DayGen';
import {HEIGHT, WIDTH} from '#utils/Dimensions';
import Metrics from '#constants/metrics/Metrics';
import Fonts from '#constants/fonts/fonts';
import SearchList from '#components/ListNews/SearchList';
interface Props {
news?: any;
}
const Header: React.FC<Props> = () => {
const date = new Date();
const dateAndDay = DateAndDayGenerator(date);
const {color} = useContext(AuthContext);
const [focused, setFocused] = React.useState(false);
const [value, setValue] = React.useState('');
const inputRef = useRef<TextInput>(null);
// animation initial value
const inputTranslateX = useRef(new Animated.Value(WIDTH)).current;
const backButtonOpacity = useRef(new Animated.Value(0)).current;
const contentTranslateY = useRef(new Animated.Value(HEIGHT)).current;
const contentOpacity = useRef(new Animated.Value(0)).current;
const handleClear = () => {
setValue('');
};
const handleBlur = () => {
setFocused(false);
const inputTranslateXConfig = {
toValue: WIDTH,
duration: 200,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
const backButtonOpacityConfig = {
toValue: 0,
duration: 50,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
const contentTranslateYConfig = {
toValue: HEIGHT,
duration: 0,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
const contentOpacityConfig = {
toValue: 0,
duration: 200,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
Animated.parallel([
Animated.timing(inputTranslateX, inputTranslateXConfig),
Animated.timing(backButtonOpacity, backButtonOpacityConfig),
Animated.timing(contentTranslateY, contentTranslateYConfig),
Animated.timing(contentOpacity, contentOpacityConfig),
]).start();
inputRef.current?.blur();
};
const handleFocus = () => {
setFocused(true);
const inputTranslateXConfig = {
toValue: 0,
duration: 200,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
const backButtonOpacityConfig = {
toValue: 1,
duration: 200,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
const contentTranslateYConfig = {
toValue: 0,
duration: 0,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
const contentOpacityConfig = {
toValue: 1,
duration: 200,
useNativeDriver: true,
easing: Easing.inOut(Easing.ease),
};
Animated.parallel([
Animated.timing(inputTranslateX, inputTranslateXConfig),
Animated.timing(backButtonOpacity, backButtonOpacityConfig),
Animated.timing(contentTranslateY, contentTranslateYConfig),
Animated.timing(contentOpacity, contentOpacityConfig),
]).start();
inputRef.current?.focus();
};
return (
<>
<SafeAreaView style={styles.header_safe}>
<View style={styles.header}>
<View style={styles.view}>
<View style={styles.Logo}>
<Image source={Logo} style={styles.image} />
</View>
{color ? (
<View style={styles.texts}>
<Text style={[styles.text, {color}]}>Nepali Congress</Text>
<Text style={styles.date}>{`${dateAndDay.day}, ${
dateAndDay.month
} ${dateAndDay.date},${' '}${dateAndDay.year}`}</Text>
</View>
) : (
<View style={styles.texts}>
<Text style={styles.text}>Nepali Congress</Text>
<Text style={styles.date}>{`${dateAndDay.day}, ${
dateAndDay.month
} ${dateAndDay.date},${' '}${dateAndDay.year}`}</Text>
</View>
)}
<TouchableOpacity onPress={handleFocus}>
<View style={styles.search}>
<Search width={25} height={25} fill="none" />
</View>
</TouchableOpacity>
<Animated.View
style={[
styles.input,
{transform: [{translateX: inputTranslateX}]},
]}>
<Animated.View style={{opacity: backButtonOpacity}}>
<TouchableOpacity
activeOpacity={1}
style={styles.back_icon}
onPress={handleBlur}>
<Back width={28} height={28} fill="#000" />
</TouchableOpacity>
</Animated.View>
<TextInput
ref={inputRef}
placeholder="Enter title, description or date of news"
placeholderTextColor="#000"
clearButtonMode="while-editing"
onFocus={handleFocus}
value={value}
onChangeText={text => {
setValue(text);
}}
style={styles.input_text}
/>
<TouchableOpacity
onPress={handleClear}
style={styles.clearButton}>
<Text style={styles.clear}>X</Text>
</TouchableOpacity>
</Animated.View>
</View>
</View>
</SafeAreaView>
<Animated.View
style={[
styles.content,
{
opacity: contentOpacity,
transform: [{translateY: contentTranslateY}],
},
]}>
<SafeAreaView style={styles.content_safe}>
<View style={styles.content_inner}>
<View style={styles.separator} />
<SearchList searchPhrase={value} />
</View>
</SafeAreaView>
</Animated.View>
</>
);
};
const styles = StyleSheet.create({
header_safe: {
zIndex: 1000,
},
header: {
height: HEIGHT * 0.087,
paddingHorizontal: 16,
backgroundColor: Colors.white,
},
view: {
flex: 1,
overflow: 'hidden',
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
position: 'relative',
},
Logo: {
margin: 10,
alignItems: 'center',
flexDirection: 'row',
width: WIDTH * 0.15,
height: HEIGHT * 0.055,
},
image: {
width: '100%',
height: '100%',
resizeMode: 'stretch',
},
texts: {
marginLeft: 4,
marginRight: WIDTH * 0.155,
},
text: {
fontSize: Metrics.h3,
color: Colors.black,
fontFamily: Fonts.type.montBold,
width: WIDTH * 0.5,
},
date: {
marginTop: 4,
fontSize: Metrics.body7,
color: Colors.black,
fontFamily: 'Mont-Regular',
},
search: {
width: 35,
height: 35,
right: 20,
borderRadius: 80,
backgroundColor: '#f5f5f5',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
input: {
height: HEIGHT * 0.087,
flexDirection: 'row',
alignItems: 'center',
position: 'absolute',
top: 0,
left: 0,
backgroundColor: Colors.white,
width: WIDTH - 32,
},
back_icon: {
width: 40,
height: 40,
borderRadius: 40,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginRight: 5,
transform: [{rotate: '180deg'}],
},
input_text: {
flex: 1,
height: 37,
backgroundColor: '#e4e6e8',
borderRadius: 80,
paddingHorizontal: 16,
fontSize: 13,
color: Colors.black,
},
input_text1: {
flex: 1,
height: 37,
backgroundColor: '#e4e6e8',
borderRadius: 80,
paddingHorizontal: 16,
fontSize: 13,
},
content: {
position: 'absolute',
width: WIDTH,
height: HEIGHT,
left: 0,
bottom: 0,
zIndex: 999,
},
content_safe: {
flex: 1,
backgroundColor: Colors.white,
},
content_inner: {
flex: 1,
paddingTop: HEIGHT * 0.087,
},
separator: {
height: 1,
marginTop: 5,
backgroundColor: '#e6e4eb',
},
search_results: {
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#e6e4eb',
marginLeft: 16,
},
clearButton: {
width: 30,
height: 30,
borderRadius: 80,
marginLeft: 10,
backgroundColor: Colors.red,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
clear: {
fontSize: 14,
color: Colors.black,
fontWeight: 'bold',
},
});
export default Header;
I have used the below model to make a handler rotate but cannot find a way to manipulate it as to make the handle rotate from where it begins instead of its center. As well, I am struggling to make the rotation occur with only one finger instead of two.
I think maybe the answer lies in the withAnchorPoint library but I’m not sure of how to apply it.
Requiring assistance 🙏🏾
import React from 'react';
import {Animated, StatusBar, Image, ImageBackground, Dimensions, StyleSheet, View, Text} from "react-native";
import { PanGestureHandler, PinchGestureHandler, State, RotationGestureHandler } from 'react-native-gesture-handler';
//import { withAnchorPoint } from 'react-native-anchor-point';
import { USE_NATIVE_DRIVER } from '../../config';
const {width} = Dimensions.get('screen');
const SIZE = width * .9;
export default class MovableClock extends React.Component {
panRef = React.createRef();
rotationRef = React.createRef();
pinchRef = React.createRef();
constructor(props) {
super(props);
/* Pinching */
this._baseScale = new Animated.Value(1);
this._pinchScale = new Animated.Value(1);
this._scale = Animated.multiply(this._baseScale, this._pinchScale);
this._lastScale = 1;
this._onPinchGestureEvent = Animated.event(
[{ nativeEvent: { scale: this._pinchScale } }],
{ useNativeDriver: USE_NATIVE_DRIVER }
);
/* Rotation */
this._rotate = new Animated.Value(0);
this._rotateStr = this._rotate.interpolate({
inputRange: [-100, 100],
outputRange: ['-100rad', '100rad'],
});
this._lastRotate = 0;
this._onRotateGestureEvent = Animated.event(
[{ nativeEvent: { rotation: this._rotate } }],
{ useNativeDriver: USE_NATIVE_DRIVER }
);
/* Tilt */
this._tilt = new Animated.Value(0);
this._tiltStr = this._tilt.interpolate({
inputRange: [-501, -500, 0, 1],
outputRange: ['1rad', '1rad', '0rad', '0rad'],
});
this._lastTilt = 0;
this._onTiltGestureEvent = Animated.event(
[{ nativeEvent: { translationY: this._tilt } }],
{ useNativeDriver: USE_NATIVE_DRIVER }
);
}
_onRotateHandlerStateChange = event => {
if (event.nativeEvent.oldState === State.ACTIVE) {
this._lastRotate += event.nativeEvent.rotation;
this._rotate.setOffset(this._lastRotate);
this._rotate.setValue(0);
}
};
_onPinchHandlerStateChange = event => {
if (event.nativeEvent.oldState === State.ACTIVE) {
this._lastScale *= event.nativeEvent.scale;
this._baseScale.setValue(this._lastScale);
this._pinchScale.setValue(1);
}
};
_onTiltGestureStateChange = event => {
if (event.nativeEvent.oldState === State.ACTIVE) {
this._lastTilt += event.nativeEvent.translationY;
this._tilt.setOffset(this._lastTilt);
this._tilt.setValue(0);
}
};
render() {
return (
<View style={styles.background}>
<StatusBar hidden={true}/>
<View style={[styles.bigQuadran]}>
</View>
<Image style={styles.numbers}
source={require("../assets/nobgfreeclock2.png")}/>
<View style={[styles.mediumQuadran]}/>
<PanGestureHandler
ref={this.panRef}
onGestureEvent={this._onTiltGestureEvent}
onHandlerStateChange={this._onTiltGestureStateChange}
minDist={10}
minPointers={2}
maxPointers={2}
avgTouches>
<Animated.View style={[styles.mover
//{transform: [{ translateX: this.translateX, }, { translateY: this.translateY}]}
]}>
<RotationGestureHandler
ref={this.rotationRef}
simultaneousHandlers={this.pinchRef}
onGestureEvent={this._onRotateGestureEvent}
onHandlerStateChange={this._onRotateHandlerStateChange}
>
<Animated.View style={[styles.mover]}>
<PinchGestureHandler
ref={this.pinchRef}
simultaneousHandlers={this.rotationRef}
onGestureEvent={this._onPinchGestureEvent}
onHandlerStateChange={this._onPinchHandlerStateChange}
>
<Animated.View style={[styles.hours,
{transform: [
{ perspective: 200 },
{ scale: this._scale },
{ rotate: this._rotateStr },
{ rotateX: this._tiltStr },
]},
]}/>
</PinchGestureHandler>
</Animated.View>
</RotationGestureHandler>
</Animated.View>
</PanGestureHandler>
{/*
<PanGestureHandler onGestureEvent={this.onPanGestureEvent}>
<Animated.View style={[styles.mover, {
transform: [{ translateX: this.translateX, }, { translateY: this.translateY}]}]}>
<View style={styles.minutes}/>
</Animated.View>
</PanGestureHandler>
<PanGestureHandler onGestureEvent={this.onPanGestureEvent}>
<Animated.View style={[styles.mover, {
transform: [{ translateX: this.translateX, }, { translateY: this.translateY}]}]}>
<View style={styles.seconds}/>
</Animated.View>
</PanGestureHandler>
*/}
<View style={[styles.smallQuadran]}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'whitesmoke',
alignItems: 'center',
justifyContent: 'center',
},
background: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'transparent'
},
mover: {
position: 'absolute',
width: SIZE,
height: SIZE,
borderRadius: SIZE/2,
alignItems: 'center',
justifyContent: 'flex-start',
top: 68
},
hours: {
backgroundColor: 'black',
height: '20%',
marginTop: '30%',
width: 4.5,
borderRadius: 4.5
},
minutes: {
backgroundColor: 'black',
height: '35%',
marginTop: '15%',
width: 3.5,
borderRadius: 3.5
},
seconds: {
backgroundColor: 'rgba(227, 71, 134, 1)',
height: '35%',
marginTop: '15%',
width: 2,
borderRadius: 2
},
bigQuadran: {
width: SIZE * 0.815,
height: SIZE * 0.815,
borderRadius: SIZE * 0.40,
backgroundColor: 'ghostwhite',
borderColor: 'black',
borderWidth: SIZE * 0.030,
position: 'absolute',
top: 100
},
smallQuadran: {
width: 10,
height: 10,
borderRadius: 5,
position: 'absolute',
backgroundColor: 'rgba(227, 71, 134, 1)',
top: 250
},
numbers: {
width: SIZE * 0.78,
height: SIZE * 0.78,
position: 'absolute',
top: 107,
borderRadius: SIZE * 4
}
})
How can I achieve this in react native?
So far I have this and I want to implement the middle curve. I don't know to either handle it with a transparent view or switch to SVG completely
and this the tabBar component
/* eslint-disable react/prop-types */
import React, { Component } from 'react'
import { TouchableOpacity, Text, StyleSheet, View } from 'react-native'
import { Colors } from 'App/Theme'
export default class TabBar extends Component {
render() {
let {
renderIcon,
getLabelText,
activeTintColor,
inactiveTintColor,
onTabPress,
onTabLongPress,
getAccessibilityLabel,
navigation,
showLabel,
} = this.props
let { routes, index: activeRouteIndex } = navigation.state
return (
<View style={styles.tabBar}>
{routes.map((route, routeIndex) => {
let isRouteActive = routeIndex === activeRouteIndex
let tintColor = isRouteActive ? activeTintColor : inactiveTintColor
return (
<TouchableOpacity
key={routeIndex}
style={styles.tab}
onPress={() => {
onTabPress({ route })
}}
onLongPress={() => {
onTabLongPress({ route })
}}
accessibilityLabel={getAccessibilityLabel({ route })}
>
{renderIcon({ route, focused: isRouteActive, tintColor })}
{showLabel ? <Text>{getLabelText({ route })}</Text> : null}
</TouchableOpacity>
)
})}
</View>
)
}
}
const styles = StyleSheet.create({
tab: {
alignItems: 'center',
flex: 1,
justifyContent: 'center',
},
tabBar: {
alignSelf: 'center',
backgroundColor: Colors.primary,
borderRadius: 50,
bottom: 10,
elevation: 2,
flexDirection: 'row',
height: 65,
position: 'absolute',
width: '95%',
},
infinity: {
width: 80,
height: 100,
},
infinityBefore: {
position: 'absolute',
top: 0,
left: 0,
width: 0,
height: 0,
borderWidth: 20,
borderColor: 'red',
borderStyle: 'solid',
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
borderBottomRightRadius: 50,
borderBottomLeftRadius: 0,
transform: [{ rotate: '-135deg' }],
},
infinityAfter: {
position: 'absolute',
top: 0,
right: 0,
width: 0,
height: 0,
borderWidth: 20,
borderColor: 'red',
borderStyle: 'solid',
borderTopLeftRadius: 50,
borderTopRightRadius: 0,
borderBottomRightRadius: 50,
borderBottomLeftRadius: 50,
transform: [{ rotate: '-135deg' }],
},
})
here is a demo: https://snack.expo.io/#nomi9995/cf371e
you need to use react-native-svg
yarn add react-native-svg
import React, { Component } from "react";
import {
Text,
StyleSheet,
View,
Dimensions,
TouchableHighlight,
} from "react-native";
import Svg, { Circle, Path } from "react-native-svg";
const tabs = [1, 2, 3, 4, 5];
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
pathX: "357",
pathY: "675",
pathA: "689",
pathB: "706",
};
}
render() {
return (
<View style={[styles.container]}>
<View style={[styles.content]}>
<View style={styles.subContent}>
{tabs.map((_tabs, i) => {
return (
<TouchableHighlight
key={i}
underlayColor={"transparent"}
onPress={() => console.log("onPress")}
>
<View>
</View>
</TouchableHighlight>
);
})}
</View>
<Svg
version="1.1"
id="bottom-bar"
x="0px"
y="0px"
width="100%"
height="100"
viewBox="0 0 1092 260"
space="preserve"
>
<Path
fill={"#373A50"}
stroke={"#373A50"}
d={`M30,60h${this.state.pathX}.3c17.2,0,31,14.4,30,31.6c-0.2,2.7-0.3,5.5-0.3,8.2c0,71.2,58.1,129.6,129.4,130c72.1,0.3,130.6-58,130.6-130c0-2.7-0.1-5.4-0.2-8.1C${this.state.pathY}.7,74.5,${this.state.pathA}.5,60,${this.state.pathB}.7,60H1062c16.6,0,30,13.4,30,30v94c0,42-34,76-76,76H76c-42,0-76-34-76-76V90C0,73.4,13.4,60,30,60z`}
/>
<Circle
fill={"#7EE6D2"}
stroke={"#7EE6D2"}
cx="546"
cy="100"
r="100"
/>
</Svg>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
overflow: "hidden",
},
content: {
flexDirection: "column",
zIndex: 0,
width: Dimensions.get("window").width - 30,
marginBottom: "4%",
left: "4%",
right: "4%",
position: "absolute",
bottom: "1%",
},
subContent: {
flexDirection: "row",
marginLeft: 15,
marginRight: 15,
marginBottom: 10,
zIndex: 1,
position: "absolute",
bottom: 5,
}
});
i hope this will help you.
Here is 2 solution according to your requirement.
If you want this type of design without selection then this code will help you :
https://github.com/alex-melnyk/clipped-tabbar
And if you need on each tab selection then here is other easy library for you :
https://github.com/Jm-Zion/rn-wave-bottom-bar
It's not obvious that this can be done with only <View/> components. I would split the TabBar into a flex row container with three subviews, and create an SVG with the filled inverted radius to be used in the center subview. To render the SVG, use react-native-svg. See a rough layout below:
...
import { SvgXml } from 'react-native-svg';
import TabCenterSvg from ‘assets/my-svg.svg’
export default class TabBar extends Component {
render() {
return (
<View style={styles.tabBar}>
<View style={styles.leftContainer}>
{/* Left Buttons */}
</View>
<View style={styles.centerContainer}>
<View style={styles.centerInnerTopContainer}>
{/* Add Button */}
</View>
<View style={styles.centerInnerBottomContainer}>
<SvgXml xml={TabCenterSvg} />
</View>
</View>
<View style={styles.rightContainer}>
{/* Right Icons */}
</View>
</View>
)
}
}
const styles = StyleSheet.create({
tabBar: {
alignSelf: 'center',
borderRadius: 50,
bottom: 10,
elevation: 2,
flexDirection: 'row',
height: 65,
position: 'absolute',
width: '95%',
},
leftContainer: {
flex: 1,
flexDirection: 'row',
borderBottomLeftRadius: 50,
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
backgroundColor: Colors.primary,
},
centerContainer: {
flex: 1,
flexDirection: 'column',
},
centerInnerTopContainer: {
flex: 1,
},
centerInnerBottomContainer: {
flex: 1,
},
rightContainer: {
flex: 1,
flexDirection: 'row',
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
borderBottomRightRadius: 50,
backgroundColor: Colors.primary,
},
})
Use this library's code and customize according to your UI
https://www.npmjs.com/package/curved-bottom-navigation-bar
Note: I'll not recommend this library as there are low weekly downloads.
Rather than using the whole library, you can use its code.
The problem is the Card View is not showing. I tried to apply it with index and position but nothing works. I need other's perspective. Thank you.
This is what I want to achieve:
Here are my codes:
return(
<View style={styles.container}>
{/* <StatusBar backgroundColor={'transparent'} translucent={true}/> */}
<MapView
style={styles.map}
initialRegion={this.state.focusedLocation}
onPress={this.pickLocationHandler}
showsUserLocation={true}
ref={ref => this.map = ref} //For animating map movement
>
{userMarker}
{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={true}
scrollEventThrottle={1}
pagingEnabled={true}
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>
{/* <TouchableOpacity onPress={this.getLocationHandler} style={styles.iconContainer}>
<Icon name="md-locate" size={30} color="blue"/>
</TouchableOpacity> */}
</View>
);
For the StyleSheet:
const styles = StyleSheet.create({
container: {
alignItems: 'center',
},
map: {
height: '100%',
width: '100%'
},
iconContainer: {
position: 'absolute',
top: 60,
right: 15,
zIndex: 1
},
//--- Style for Marker -----//
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)",
},
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",
}
})
Try using these styles:
container: {
flex: 1
},
map: {
flex: 1,
...StyleSheet.absoluteFillObject,
top: 0, left: 0, right: 0, bottom: 25
},
scrollView: { // Or for a simple View or Card
// ...
position: 'absolute',
bottom: 0,
zIndex: 100,
}
I am able to get it to the center without the mapview but I cant seem to get the image to the center with mapview. anyone able to do it on react native?
render() {
return (
<View style = { styles.container }>
<MapView style = { styles.mapView }></MapView>
<View style = { styles.mapCenterMarkerView }>
<Image style={styles.mapCenterMarker}
source={{uri: this.state.markerIcon}}/>
</View>
);
}
var styles = StyleSheet.create({
container: {
flex: 1,
},
mapView: {
flex: 1
},
mapCenterMarkerView: {
top: 0,
position: 'absolute',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapCenterMarker: {
width: 32,
height: 32,
},
});
I was able to get the result you're looking for, but I had to remove the flex styling from the MapView.
https://rnplay.org/apps/TQGKjA
It looks like MapView doesn't allow child nodes. There's probably a way to do this without resorting to position: 'absolute' for the MapView but I'd have to play with it some more.
If you're new to flexbox like me, I've found this to be a good resource:
flexboxin5.com
class SampleApp extends React.Component {
render() {
return (
<View style={ styles.container }>
<MapView style={ styles.mapView }></MapView>
<View style={styles.mapCenterMarker} />
</View>
);
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapView: {
position: 'absolute',
top: 20,
bottom: 0,
left: 0,
right: 0,
},
mapCenterMarkerView: {
flex: 1,
},
mapCenterMarker: {
width: 32,
height: 32,
backgroundColor: 'black'
},
});
I move the justifyContent: 'center' down from container for it to work. thank to you because i have a inside the .
container: {
flex: 1,
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapView: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
mapCenterMarkerView: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapCenterMarker: {
width: 32,
height: 32,
backgroundColor: 'rgba(0,0,0,0)'
},