enter image description here
I'm trying to change the layout of the images which are showing below I want to show them on the top I just want to change the layout of the images which are showing below I want to show them above the first card
export default function App({navigation}) {
const [index, setIndex] = React.useState(0);
const onSwiped = () => {
transitionRef.current.animateNextTransition();
setIndex((index + 1) % data.length);
};
return (
<SafeAreaView style={styles.container}>
<View
style={{
backgroundColor: 'black',
opacity: 0.05,
transform: [{rotate: '45deg'}, {scale: 1.6}],
position: 'absolute',
left: -15,
top: 30,
}}></View>
<View style={styles.swiperContainer}>
<Swiper
ref={swiperRef}
cards={data}
cardIndex={index}
renderCard={card => <Card card={card} />}
infinite
backgroundColor={'transparent'}
onSwiped={onSwiped}
onTapCard={() => swiperRef.current.swipeLeft()}
cardVerticalMargin={50}
stackSize={stackSize}
animateCardOpacity={true}
stackScale={8}
stackSize={3}
verticalSwipe={false}
stackSeparation={13}
animateOverlayLabelsOpacity
animateCardOpacity
disableTopSwipe
disableBottomSwipe
/>
</View>
</SafeAreaView>
);
}
Change this in your styles: top: 30 => top: -30
Use stackseparation. stackSeparation={-20}
Related
In react native tab view when I scroll to the bottom and slide to the next page when I am getting black space. Is there any way I can re-render the slide from top:
const renderTabs = () => {
return (
<>
<TabView
onIndexChange={index => setIndex(index)}
navigationState={{index: tabIndex, routes}}
renderScene={renderScene}
renderTabBar={renderTabBar}
initialLayout={{
height: 0,
width: Dimensions.get('window').width,
}}
// lazy
/>
</>
);
};
const renderTabBar = props => {
const y = scrollY.interpolate({
inputRange: [0, HeaderHeight],
outputRange: [HeaderHeight, 0],
extrapolateRight: 'clamp',
});
return (
<Animated.View
style={{
top: 0,
zIndex: 1,
position: 'absolute',
transform: [{translateY: y}],
width: '100%',
}}>
<TabBar
{...props}
onTabPress={({route, preventDefault}) => {
if (isListGliding.current) {
preventDefault();
}
}}
style={styles.tab}
renderLabel={renderLabel}
scrollEnabled={true}
indicatorStyle={styles.indicator}
/>
</Animated.View>
);
};
The next slide should not be taking white space - when I touch to screen and try to slide up then only it will become responsive
I am trying to create a bottom tab navigation in react native which is having a blur effect but as I am using it above the bottomsheet so navigation bar is getting hide or will have to manage with bottomInset property of bottomsheet.
This is tab navigation coming above bottom sheet
This is actually I want it to look
<BottomSheet
ref={bottomSheetRef}
visible={bottomSheetVisible}
onChangeCallback={onChangeCallback}
enablePanDownToClose={false}
header={header}
bottomInset={84} // due to this I am able to add it above the bottomsheet
style={styles.bottomSheet}
renderBackdrop={renderBackdrop}>
</BottomSheet>
Custom Backdrop
const CustomBackdrop = ({animatedIndex, style}: BottomSheetBackdropProps) => {
// animated variables
const containerAnimatedStyle = useAnimatedStyle(() => ({
opacity: interpolate(
animatedIndex.value,
[1, 1],
[1, 1],
Extrapolate.CLAMP,
),
}));
// styles
const containerStyle = useMemo(
() => [style, styles.container, containerAnimatedStyle],
[style, containerAnimatedStyle],
);
return (
<Animated.View style={containerStyle}>
<View>
<WalletHomeHeader />
<WalletHomeCard />
</View>
<NavigationBar />
</Animated.View>
);
};
export default CustomBackdrop;
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
justifyContent: 'space-between',
},
});
Style in Tab Navigator
tabBarActiveTintColor: theme.white,
tabBarInactiveTintColor: theme.secondaryGrey,
tabBarStyle: {
position: 'absolute',
bottom: 0,
paddingVertical: scaleHeight(15),
backgroundColor: convertHexToRGBA(theme.neutral_700, 0.5),
borderTopWidth: 1,
borderTopColor: theme.grey,
},
my button doesn't work when I set it to absolute position, when setting is to be on top of a carousel... I suppose it is getting under something because when removing the absolute it works normally, but I don't know how to solve it
Short code:
export default class SpaceDetail extends React.Component {
state = {
optionSelected: "Fotos",
favorite: true,
};
render() {
return (
<ScrollView indicatorStyle="black">
<ContainerPhotoMap>
{this.state.optionSelected === "Fotos" ? <Carousel /> : <Maps />}
</ContainerPhotoMap>
<ButtonFavorite
onPress={() => {this.setState({favorite: !this.state.favorite})}}
>
<MaterialIcons
name={this.state.favorite ? "favorite" : "favorite-border"}
size={40}
color="white"
/>
</ButtonFavorite>
</ScrollView>
);
}
}
Short Style Code:
export const ContainerPhotoMap = styled(View)`
max-width: 200px;
`;
export const ButtonFavorite = styled(Button)`
position: absolute;
right: 0;
`;
Short carousel code:
export default class Carousel extends React.Component {
state = {
active: 0,
};
change = ( {nativeEvent} : {nativeEvent:any} ) => {
const slide = Math.ceil(
nativeEvent.contentOffset.x / nativeEvent.layoutMeasurement.width
);
if (slide !== this.state.active) {
this.setState({ active: slide });
}
};
render() {
return (
<View style={{ width, height }}>
<ScrollView
pagingEnabled
scrollEnabled
horizontal
onScroll={this.change}
showsHorizontalScrollIndicator
style={{ width, height }}
>
{images.map((image, index) => (
<Image
key={index}
source={{ uri: image }}
style={{ width, height, resizeMode: "cover" }}
/>
))}
</ScrollView>
<View
style={{
flexDirection: "row",
position: "absolute",
bottom: 0,
alignSelf: "center",
}}
>
{images.map((i, k) => (
<Text
key={k}
margin="3px"
color={k === this.state.active ? "white" : ""}
>
⬤
</Text>
))}
</View>
</View>
);
}
}
Style Carousel:
export const ViewCarousel = styled(View)`
width: width;
height: height;
position: relative;
`;
Button print on the right,
There is no transform-origin property in react-native so how can I do it ?
I think I should use transformX & transformY props.
const Marker = () => {
const rotate = new Animated.Value(???);
const transformX = new Animated.Value(???);
const transformY = new Animated.Value(???);
const doRotation = (newDegValue) => {
// ?????
}
return (
<View style={{ width: 200, height: 200, justifyContent: 'center', alignItems: 'center' }}>
<Animated.View transform={[{ rotate }, { transformX }, { transformY }]}>
<ArrowIcon width={30} height={30}>
</Animated.View>
{/* I need to rotate my ArrowIcon around this BaseIcon */}
<BaseIcon width={100} height={100} />
<View/>
)
}
Explanation
In this example, I am using the Animated Library. First, we are defining a Animated Value in the constructor. Then we are creating a triggerAnimation function, where we will animate this new value over time using the timing function.
In the render function, we are defining a new style object called animatedStyle. This style object will handle the rotation of the arrow. We are using the interpolate function to incrementally rotate the arrow. As inputRange we are allowing -1 to +1. -1 means a rotation of -360° and +1 a rotation of 360°-, as you can see in the outputRange.The interpolate function will automatically handle the mapping between input and output range.
In the return statement we are passing the animatedStyle to our <Animated.View>.
Now we can call the triggerAnimation function. As parameter we have to pass the desired rotation value.
Some Examples:
this.triggerAnimation(0.5) would result in a rotation of +180°.
this.triggerAnimation(-0.5) would result in a rotation of -180°.
this.triggerAnimation(0.25) would result in a rotation of +90°.
this.triggerAnimation(0.75) would result in a rotation of +270°.
Code
Constructor and triggerAnimation function:
constructor(props){
super(props);
this.state={
currentRotation: 0,
value: new Animated.Value(0),
}
}
triggerAnimation(newValue){
Animated.timing(this.state.value, {
toValue: newValue,
duration: 500,
}).start(() => {
// set rotated again
this.setState({currentRotation: newValue})
});
}
render function:
render() {
const animatedStyle={
transform: [
{
rotateZ: this.state.value.interpolate({
inputRange: [-1,1],
outputRange: ['-360deg', `360deg`],
}),
},
],
};
return (
<View style={styles.container}>
<View style={{justifyContent: 'center', flexDirection: 'column', alignItems: 'center', width: 150, height: 150}}>
<Animated.View style={[{justifyContent: 'center', flexDirection: 'row', alignItems: 'flex-start'}, StyleSheet.absoluteFill,animatedStyle]} >
<Icon name={"location-arrow"} size={30} style={{transform: [ {rotateZ: '-45deg' }]}}/>
</Animated.View>
<View style={{width: 70, height: 70, borderRadius: 35, backgroundColor: 'blue'}}/>
</View>
<TouchableOpacity onPress={()=>this.triggerAnimation(0.5)} >
<Text> 180° Trigger Animation </Text>
</TouchableOpacity>
...
</View>
);
}
Working Demo
https://snack.expo.io/B1UzO79Cr
You can use
transform: [{ rotate: '40deg' }] in styles
Example: => https://snack.expo.io/#msbot01/mad-cookie
export default class App extends React.Component {
constructor(props){
super(props)
this.state=({
angle:0
})
}
rotate(){
this.setState({
angle: this.state.angle + 5
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={()=>{this.rotate()}} style={{position: "absolute", top:20, width:'100%'}}>
<Text style={{marginTop:20, position:'absolute', top:20}}>Click on me to rotate</Text>
</TouchableOpacity >
<Image style={{height:40, width:40}} source={require('./bus.png')} />
<View onPress={()=>{this.rotate()}} style={{position: "absolute"}}>
<Image style={{height:150, width:150, transform: [{ rotate: (this.state.angle+'deg') }]}} source={require('./ss.png')} />
</View >
</View>
);
}
}
I have a ScrollView that has a top section with one background colour and a bottom section with another different colour.
When a user scrolls past the content and the view bounces (elastic over-extend), how could I make it so the background is consistent with either the top or the bottom, depending on the scroll direction?
I wouldn't play with the contentInset and contentOffset of the ScrollView as if your content changes, it might change the position of your scrollview.
You can do something very simple by just adding a View at the very top of your ScrollView:
// const spacerHeight = 1000;
<ScrollView>
{Platform.OS === 'ios' && (
<View
style={{
backgroundColor: 'red',
height: spacerHeight,
position: 'absolute',
top: -spacerHeight,
left: 0,
right: 0,
}}
/>
)}
</ScrollView>
On iOS, you can render a spacer View on top of the ScrollView, and use contentInset to render it "off-screen", contentOffset to set the initial scroll position to offset the inset:
render() {
const isIos = Platform.OS === 'ios'
const SPACER_SIZE = 1000; //arbitrary size
const TOP_COLOR = 'white';
const BOTTOM_COLOR = 'papayawhip';
return (
<ScrollView
style={{backgroundColor: isIos ? BOTTOM_COLOR : TOP_COLOR }}
contentContainerStyle={{backgroundColor: TOP_COLOR}}
contentInset={{top: -SPACER_SIZE}}
contentOffset={{y: SPACER_SIZE}}>
{isIos && <View style={{height: SPACER_SIZE}} />}
//...your content here
</ScrollView>
);
}
Because contentInset and contentOffset are iOS only, this example is conditioned to degrade gracefully on Android.
The accepted solution did not work well for me because I need to put flexGrow: 1 on the contentContainerStyle. Using insets/offsets didn't make the content grow the way I want, otherwise it worked not so bad.
I have another solution to suggest: putting a bicolor background layer under a transparent ScrollView, and add colors to your scrollview content. This way, on ios bounce, the bicolor layer under the scrollview will reveal itself.
Here's what I mean by bicolor layer (here the scrollview is empty and transparent)
Now if I put back the ScrollView children (which if a body with blank background, and a footer with yellow background), I get this:
As long as you don't bounce more than 50% of the scrollview height, you will see the appropriate background color.
Here's a component you can use to wrap your scrollview.
const AppScrollViewIOSBounceColorsWrapper = ({
topBounceColor,
bottomBounceColor,
children,
...props
}) => {
return (
<View {...props} style={[{ position: 'relative' }, props.style]}>
{children}
<View
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: -1, // appear under the scrollview
}}
>
<View
style={{ flex: 1, backgroundColor: topBounceColor }}
/>
<View
style={{ flex: 1, backgroundColor: bottomBounceColor }}
/>
</View>
</View>
);
};
And here's how you use it:
<AppScrollViewIOSBounceColorsWrapper
style={{flex: 1}}
topBounceColor="white"
bottomBounceColor="yellowLancey"
>
<ScrollView style={{flex: 1}}>
<WhiteBackgroundBody/>
<YellowBackgroundFooter />
</AppScrollView>
</AppScrollViewIOSBounceColorsWrapper>
Make sure to NOT set a background color to the scrollview, otherwise the bicolor layer will never reveal itself (backgroundColor on contentContainerStyle is fine)
This is, I think the most stupid simple way i found to do it:
<ScrollView style={{backgroundColor: '#000000'}}>
[...]
<View style={{position: "absolute", bottom: -600, left: 0, right: 0, backgroundColor: '#FFFFFF', height: 600}}/>
</ScrollView>
You may adjust the height/bottom absolute value to your likings depending on how far you think the user could scroll.
I personally implemented that into a <ScrollBottom color={"white"}/> component for ease of use in all my ScrollViews
For me, the simplest solution is modification based on Sebastien Lorber answer which doesn't include wrapping, just calling it before (or after) ScrollView component:
Create component:
interface IScrollViewBackgroundLayer {
topBounceColor: string;
bottomBounceColor: string;
}
export const ScrollViewBackgroundLayer = ({
topBounceColor,
bottomBounceColor,
}: IScrollViewBackgroundLayer): ReactElement => (
<View
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: -1, // appear under the scrollview
}}>
<View style={{ flex: 1, backgroundColor: topBounceColor }} />
<View style={{ flex: 1, backgroundColor: bottomBounceColor }} />
</View>
);
and use it like this:
return (
<SafeAreaView style={styles.container}>
<ScrollViewBackgroundLayer topBounceColor={topBounceColor} bottomBounceColor={bottomBounceColor} />
<ScrollView>
...
</ScrollView>
</SafeAreaView>