How to create a bottom tab navigation above bottomsheet in react native? - javascript

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,
},

Related

React Native, content going under navigation header, SafeAreaView not working

As you can see in the image below, I have to give some top margin in order to "not" hide my half of the content under the navigation header, isn't header supposed to be a "safe area" for the below content, to be on the safe side I provided the SafeAreaView but still my content goes under the Header and unfortunately I have to give some hardcoded margin top value to avoid hiding.
The above image is when I comment marginTop.
Above image is when I add marginTop: 70
Code:
NotificationScreen.tsx:
import {
View,
SafeAreaView,
Text,
StatusBar,
} from 'react-native';
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated';
import OrderItem from '../../components/OrderItem';
const NotificationScreen = () => {
const [orders, setOrders] = useState([]);
useEffect(() => {
// calling API...
}, []);
return (
<SafeAreaView style={styles.container}>
<StatusBar backgroundColor="transparent" translucent />
<Text style={{color: 'lightgray', fontSize: 18}}>My Orders: </Text>
<Animated.FlatList
data={orders}
entering={FadeIn}
leaving={FadeOut}
contentContainerStyle={{
alignItems: 'center',
}}
keyExtractor={(_: any, index) => 'key' + index}
renderItem={({item}) => <OrderItem key={item.id} data={item} />}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
marginTop: 70, // if I remove this, the content goes under the header as shown in image.
flex: 1,
padding: 10,
backgroundColor: COLORS.primary,
},
});
export default NotificationScreen;
One more query, why my OrderItem not taking the full width of FlatList (see image, the gray box is not takin the full width...), I have provided width: 100% to my OrderItem container:
OrderItem.tsx:
const OrderItem = ({data}) => {
return (
<View style={styles.container}>
<View style={styles.textBlock}>
<Text style={styles.label}>Strategy: </Text>
<Text style={styles.info}>{data.strategyTitle}</Text>
</View>
// ... same views as shown in image
</View>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
paddingVertical: 10,
paddingHorizontal: 10,
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: COLORS.lightGray,
borderRadius: 10,
},
textBlock: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
label: {
color: 'grey',
fontSize: 16,
},
info: {
color: 'white',
fontSize: 16,
},
});
export default OrderItem;
The SafeAreaView does not work currently for Android devices. You need to have something like this to avoid this issue:
import { Platform,StatusBar } from "react-native";
const styles = StyleSheet.create({
container: {
paddingTop: Platform.OS == "android" ? StatusBar.currentHeight : 0,
},
});
<SafeAreaView style={styles.container}>
</SafeAreaView>
And for the OrderItem not taking all available width, remove from Animated.FlatList this:
contentContainerStyle={{alignItems: 'center'}}

Weird padding on View in react native web on Edge

I was creating a Button in react native (on web). If I view the button in Edge, a very weird padding appears. I tried to debug but I can't get a fix. It works correctly on Android and Firefox.
I think there is some problem with Edge's renderer (Blink) because the code works correctly in firefox and on android (native).
Here is the code for the component:
import React, { useState } from 'react';
import { View, Animated, Easing, Image, StyleSheet, Pressable, Text } from 'react-native';
import { Hoverable } from 'react-native-web-hooks';
const Button = () => {
const [animatedButtonPressed] = useState(new Animated.Value(0));
const [animatedButtonHover] = useState(new Animated.Value(0));
const animate = (value, toValue, duration = 150, easing = Easing.linear) => {
Animated.timing(value, {
toValue: toValue,
duration: duration,
easing: easing,
// change later
useNativeDriver: false
}).start();
}
const animatedTextStyle = {
color: animatedButtonPressed.interpolate({
inputRange: [0,1],
outputRange: ["#fff" , "#2b7f3c"]
})
}
const animatedButtonStyle = {
backgroundColor: animatedButtonHover.interpolate({
inputRange: [0,1],
outputRange: ["#2b7f3c", "transparent"]
}),
}
const animatedButtonPressedStyle = {
backgroundColor: animatedButtonPressed.interpolate({
inputRange: [0,1],
outputRange: ["#fff", "red"]
}),
}
let Handlers = (props) => {
return (
<>
<Pressable onPressIn={() => animate(animatedButtonPressed, 1)} onPressOut={() => animate(animatedButtonPressed, 0)}>
<Hoverable onHoverIn={() => animate(animatedButtonHover, 1)} onHoverOut={() => animate(animatedButtonHover, 0)}>
<View {...props}/>
</Hoverable>
</Pressable>
</>
)
}
let Backgrounds = (props) => {
return (
<Animated.View style={animatedButtonPressedStyle}>
<Animated.View style={animatedButtonStyle}>
<View {...props}/>
</Animated.View>
</Animated.View>
)
}
return (
<View style={styles.container}>
<View style={styles.button}>
<Backgrounds>
<Handlers>
<View style={styles.padding}>
<Animated.Text style={[styles.text, animatedTextStyle]}>Hello</Animated.Text>
</View>
</Handlers>
</Backgrounds>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignSelf: 'flex-start',
overflow: 'hidden',
},
button: {
borderRadius: 3,
borderWidth: 2,
borderColor: 'green',
},
padding: {
paddingHorizontal: 10,
paddingVertical: 5,
},
text: {
color: 'white',
fontSize: 16
}
});
export default Button;
I think this is unfortunately a symptom of using React-native on the web things get squashed and you won't have as much control for cross browser quirks.
Is there any reason you didn't use ReactJS?

react native deck swiper library

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}

How to create custom dropdown list in react-native?

I almost consume 17 hours, but the answers on what I have searched did not satisfy the exact answer to my question,
how to create own custom DropdownList in react native? I already did, the 1st child node which is DropDown (cyan) is work properly, the 2nd child node which is the the List (green) with absolute position but it was not work properly, unless the root parent (red) will also covered the 2nd child node with absolute position, to make it active and clickable, as like what I mention from the picture, Figure 1.0
I set absolute position of the List (green) to make it float from the next child node and the error was persist, the List(parent) was disabled and it cannot click each child items (yellow), unless I set height of the root parent (red) that covered the entire child node but it leads to the next node to adjust the position and do the unexpected layout, like the sample picture Figure 1.1
I DID IT!, the problem is the root parent (red) must not have customized styled property, and I still have one questions, I dont know if it is bug or what, once I did not put any custom property in the style of root parent it works properly, and here is my source code
App.js
import React, { useState } from 'react';
import Separator from './Separator';
import Spinner from './Spinner';
import {
View,
Text,
TouchableOpacity
} from 'react-native';
export default function () {
const [spBusiness, setSPBusiness] = useState({
showList: false,
selectedItem: ''
})
const onShowList = () => {
if (spBusiness.showList) {
setSPBusiness(prev => ({
...prev,
showList: false
}))
}
else {
setSPBusiness(prev => ({
...prev,
showList: true
}))
}
}
const onSelectItem = (item, index) => {
setSPBusiness(prev => ({
showList: false,
selectedItem: item
}));
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#fff' }}>
<Box text='Rectangle 1' onPress={() => console.log('Rect 1')} />
<Separator vertical={1} />
<Spinner
placeholder='Select Item'
items={['A', 'B', 'C']}
isListShow={spBusiness.showList}
selectedItem={spBusiness.selectedItem}
onShowList={onShowList}
onSelectItem={onSelectItem}
/>
<Separator vertical={1} />
<Box text='Rectangle 2' onPress={() => console.log('Rect 2')} />
<Separator vertical={1} />
</View>
)
}
const Box = props => (
<TouchableOpacity onPress={props.onPress} style={{ zIndex: -1, borderRadius: 7.5, width: 250, height: 45, justifyContent: 'center', alignItems: 'center', backgroundColor: '#242424' }}>
<Text style={{ color: '#fff' }}>{props.text}</Text>
</TouchableOpacity>
)
DropDownList/index.js
import React from 'react';
import styles from './style';
import AIcon from 'react-native-vector-icons/AntDesign';
import {
View,
Text,
Dimensions,
TouchableOpacity,
ScrollView
} from 'react-native';
import Separator from '../Separator';
export default function (props) {
const { items } = props;
const { width, height } = Dimensions.get('window');
const size = size => (size / 100) * width;
const hp = hp => (hp / 100) * height;
const wp = wp => (wp / 100) * width;
return (
<View>
{/* here is the root parent with empty style property*/}
<TouchableOpacity
style={styles.skin}
activeOpacity={0.75}
onPress={props.onShowList}
>
<View style={styles.body}>
<View style={styles.upperBodyPane}>
</View>
<View style={styles.centerBodyPane}>
{props.selectedItem.length === 0 &&
<Text>{props.placeholder}</Text>
}
{props.selectedItem.length !== 0 &&
<Text>{props.selectedItem}</Text>
}
<AIcon name='caretdown' size={size(3.5)} color='#242424' />
</View>
</View>
</TouchableOpacity>
{props.isListShow &&
<ScrollView
style={styles.list}
contentContainerStyle={styles.listContainer}
>
{
items.map((item, index) => (
<View key={index}>
<Item
item={item}
onPress={() => props.onSelectItem(item, index)}
/>
{items.length !== (index + 1) ? <Separator vertical={0.5} /> : null}
</View>
))
}
</ScrollView>
}
</View>
)
}
const Item = props => (
<TouchableOpacity style={styles.item} onPress={props.onPress}>
<Text style={styles.itemText}>{props.item}</Text>
</TouchableOpacity>
)
DropDownList/style.js
import {
Dimensions,
StyleSheet
} from 'react-native';
const { width, height } = Dimensions.get('window');
const size = size => (size / 100) * width;
const hp = hp => (hp / 100) * height;
const wp = wp => (wp / 100) * width;
export default StyleSheet.create({
skin: {
minWidth: wp(70),
height: hp(5.5),
paddingHorizontal: wp(6),
justifyContent: 'center',
backgroundColor: 'cyan',
position: 'relative'
},
body: {
},
centerBodyPane: {
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
},
item: {
height: hp(5),
paddingHorizontal: wp(5),
justifyContent: 'center',
backgroundColor: 'orange',
},
itemText: {
color: 'white'
},
list: {
top: hp(6.5),
width: wp(70),
maxHeight: hp(15),
backgroundColor: 'green',
position: 'absolute',
},
listContainer: {
padding: size(1.75),
}
})
but the worse case only, I need to set the next child node of DropDownList to zIndex: -1 , but it finally works.

toggle modal screen from header react native

Hi I want to toggle a transparent modal screen from the header button, im using hooks
Heres my stack component
function MyStack(props) {
const [modalvisble, setModalvisble] = useState(false)
ToggleModal = () => {
console.log(modalvisble)
setModalvisble(!modalvisble)
}
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="MyTabs"
screenOptions={{
header: ({ ToggleModal }) => {
return (
<Header
ToggleModal={()=>ToggleModal}
/>
)
},
cardStyle: { backgroundColor: 'rgba(52, 52, 52, 0.8)',},
cardStyleInterpolator: ({ current: { progress } }) => ({
cardStyle: {
opacity: progress.interpolate({
inputRange: [0, 0.5, 0.9, 1],
outputRange: [0, 0.25, 0.7, 1],
}),
overlayStyle: {
opacity: progress.interpolate({
inputRange: [0, 1],
outputRange: [0, .5],
extrapolate: 'identity',
})
}
}
})
}}
mode='modal'
>
<Stack.Screen
name="MyTabs"
component={MyTabs}
options={{
}}
/>
<Stack.Screen name="ModalScreen" component={ModalBar} modalvisble={modalvisble} />
</Stack.Navigator>
</NavigationContainer>
);
}
Header Component
function Header({ ToggleModal }) {
//const navigation = useNavigation();
// const toggleIsFocused = () => {
// selected ? navigation.navigate('Mytab') : navigation.navigate('ModalScreen')
// return toggleSelected;
// }
return (
<View>
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 30, marginRight: 20, }}>
<Text style={{ color: 'white', margin: 10, fontSize: 13 }}>User Name</Text>
<TouchableOpacity
//onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
onPress={ ToggleModal}
/>
</View>
</View>
)
}
export default Header;
Modal Screen
function ModalBar({modalvisble}) {
return (
<Modal style={{ flex: 1, }} visible={modalvisble} />
)
}
I try to pass function from parent component to child / or reverse, but still, do not work.
Goal is like using the user name icon to open modal screen for some info, and press again to close modal screen, with same button.
Thanks!!
First, ToggleModal={()=>ToggleModal} this won't actually call ToggleModal function. Instead you should write ToggleModal={() => ToggleModal()}, or just ToggleModal={ToggleModal}.
Second, you dont need to pass ({ ToggleModal }) => {...} as an argument. ToggleModal function is already defined and visible.
Last, you need to use setState(prevState => nextState) form of setState, because otherwise modalVisible will always be seen as true in that function (it won't update, unless you use useCallback) and the function will always set it to false. Here's the code setModalVisible(modalVisible => { return !modalVisible }).

Categories