How to hide keyboard while open the drawer - react-native

I want to hide the keyboard when I open the drawer but when I run the app it just opens the drawer without dismissing the keyboard. here is my code
useLayoutEffect(() => {
navigation.setOptions({
headerTitleAlign:'center',
headerLeft:() =>(
/*open drawer and dismiss keyboard*/
<TouchableWithoutFeedback onPress={() =>{Keyboard.dismiss;navigation.openDrawer()}}>
<View style={styles.menuIcon}>
<MaterialIcon name="menu" size={30} />
</View>
</TouchableWithoutFeedback>
),
how can I do to fix it?

dismiss is a method. You have to call it like this :
Keyboard.dismiss();
So, change you code with the following :
useLayoutEffect(() => {
navigation.setOptions({
headerTitleAlign:'center',
headerLeft:() =>(
/*open drawer and dismiss keyboard*/
<TouchableWithoutFeedback
onPress={() =>{
Keyboard.dismiss(); //Call it
navigation.openDrawer()
}}
>
<View style={styles.menuIcon}>
<MaterialIcon name="menu" size={30} />
</View>
</TouchableWithoutFeedback>
),
})
})
More detail is here

Related

Bug between navigation screens and modal

So my problem is kind of weird,when i navigate between screens it seems to let the modal open but invisible.Lets say that i have a modal on my home page and pressing the menu button it opens the modal and i start navigate ,when i press the button again to open the modal and navigate to another screen it navigates but it lets open an invisible modal.
Anyone knows what kind of bug this is?
Code below :
export default function Header() {
//Use of navigation Hook
const navigation = useNavigation();
//Modal Constructor
const [modalVisible,setModalVisible] = useState(false);
return (
// Container
<View style = {styles.Header}>
{/* Modal */}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
<View style = {styles.modalStyle}>
{/* Pressable and Text for each functionality */}
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('Home')}>
<Text style = {styles. textInsideModalPressables}>Home</Text>
</Pressable>
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('Profile')}>
<Text style = {styles. textInsideModalPressables}>Profile</Text>
</Pressable>
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('Settings')}>
<Text style = {styles. textInsideModalPressables}>Settings</Text>
</Pressable>
<Pressable style = {styles.pressable} onPress = { () => navigation.navigate('LogInPage')}>
<Text style = {styles. textInsideModalPressables}>Log Out</Text>
</Pressable>
<Pressable onPress={ () => {setModalVisible(!modalVisible)}} style = {styles.pressable}>
<Text style = {styles. textInsideModalPressables}>Close modal</Text>
</Pressable>
</View>
</Modal>
{/* Pressable Mechanism in order to open the Modal */}
<Pressable onPress={ () => {setModalVisible(!modalVisible)}} style = {styles.pressableMenu}>
<SimpleLineIcons style = {styles.iconMenu} name="menu" size={Dimensions.get('window').width > 800 ? 40 : 24 } color="white" />
<Text style = {styles.menuText}>Menu</Text>
</Pressable>
<Text style = {styles.nameText}> E-Library</Text>
</View>

Bottom Sheet doesn't close when navigating to different screen

I'm new to programming and when I navigate to the new screen and the bottom sheet doesn't close here's the picture of it. I'm using #gorhom/bottom-sheet^4.I have done some research and I know that using useFocusEffect could acheive it but i dont really know how. Can someone help me on this?
<BottomSheetModal
enablePanDownToClose={true}
ref={bottomSheetModalRef}
index={0}
snapPoints={snapPoint}
backdropComponent={renderBackdrop}
>
<View>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Settings");
}}
>
<Text style={styles.modalText}>Settings</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Saved");
}}
>
<Text style={styles.modalText}>Saved</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Delete");
}}
>
<Text style={styles.modalText}>Delete</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={() => {}}>
<Text style={styles.modalText}>Log out</Text>
</TouchableWithoutFeedback>
</View>
</BottomSheetModal>
There are few ways to do it. Here are two:
Add useFocusEffect that runs when your screen with BottomSheetModal is unfocused:
useFocusEffect(
React.useCallback(() => {
return () => bottomSheetRef.current?.close()
}, [])
);
Close BottomSheetModal, whenever you are leaving your screen. In order to do that, you have to call bottomSheetModalRef.current?.close while navigating:
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Settings");
bottomSheetModalRef.current?.close();
}}
>
<Text style={styles.modalText}>Settings</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Saved");
bottomSheetModalRef.current?.close();
}}
>
<Text style={styles.modalText}>Saved</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
navigation.navigate("Delete");
bottomSheetModalRef.current?.close();
}}
>
<Text style={styles.modalText}>Delete</Text>
</TouchableWithoutFeedback>
If you're using React Navigation you can also automatically close any open modals whenever navigation changes like so:
import { useBottomSheetModal } from '#gorhom/bottom-sheet'
const Navigation = () => {
const { dismissAll: dismissAllModals } = useBottomSheetModal()
return <NavigationContainer
onStateChange={() =>
dismissAllModals()
}>
{...}
</NavigationContainer>
}

React-Native modal not showing FlatList Items

Modal only displays button but not FlatList item.
I am trying to build a custom app picker for my react-native-app which renders a list of items on a modal.
AppPicker.js
const AppPicker = ({ icon, items, placeholder }) => {
const [modalVisible, setModalVisible] = React.useState(false)
return (
<>
<TouchableWithoutFeedback onPress={() => setModalVisible(true)} >
<View style={styles.container}>
{icon && <MaterialCommunityIcons name={icon} size={20} style={styles.icon} />}
<AppText style={styles.text}> {placeholder} </AppText>
<MaterialCommunityIcons name="chevron-down" size={20} />
</View>
</TouchableWithoutFeedback>
<Modal visible={modalVisible} animationType="slide" >
<Button title="Close" onPress={() => setModalVisible(false)} />
<FlatList
data={items}
keyExtractor={item => item.value.toString()}
renderItem={({ item }) =>
<PickerItem
lable={item.label}
onPress={() => console.log(item)}
/>}
/>
</Modal>
</>
)
}
the <PickerItem/> that should be rendered by the flatlist is a component that just displays the items from the list.
PickerItem.js
const PickerItem = ({ label, onPress }) => {
return (
<TouchableOpacity onPress={onPress}>
<AppText> {label} </AppText>
</TouchableOpacity>
)
}
export default PickerItem;
when I randomly tap on the modal screen however the onPress() on the FlatList triggers the console.log(item) and the items are displayed on the console. Any help on this will be appreciated.
** App.js **
const categories = [
{ label: "furniture", value: 1 },
{ label: "clothing", value: 2 },
{ label: "phone", value: 3 },
]
export default function App() {
return (
<Screen style={styles.container}>
<AppPicker items={categories} icon="apps" placeholder="category" />
<AppTextInput icon="email" placeholder="email" />
</Screen>
);
}
NOTE: I am using expo to run the application.

react naviagation v5 navigate from drawer custom view

I am using React Navigation V5, I wanna custom drawer Navigation content which contents the image on top and some others navigation items unders
Here is my drawer items:
Image (custom view)
Profile
Products
Orders
Here is my code my custom drawer content.
export const CustomDrawerContent = props => {
return (
<SafeAreaView style={styles.customDrawer}>
<View
style={{ flex: 1 }}
>
<DrawerContentScrollView {...props}>
<TouchableNativeFeedback onPress={() => { console.log('go profile'); }}>
<View style={styles.userContainer}>
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={{ uri: 'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTLCta_MQcJFd2kpz8HwXFm-6vxVqXzRUgCOIuhs94Q32GG8EeJ' }}
/>
</View>
<Text style={styles.name}>Nguyen van Admin</Text>
</View>
</TouchableNativeFeedback>
<DrawerItemList {...props} />
</DrawerContentScrollView>
<DrawerItem
label="Đăng xuất"
style={{
borderWidth: 1,
}}
labelStyle={{
color: 'black'
}}
icon={({ focused, color, size }) => <Ionicons
size={23}
color={color}
name={Platform.OS === 'android' ? 'md-exit' : 'ios-exit-outline'}
/>}
/>
</View>
</SafeAreaView>
);
}
So If the profile screen existed in drawer, By clicking to the image i can use
props.navigate("profile")
But if I remove the profile screen from the drawer screens. I can not navigate to profile anymore.
How do i archive navigate to profile screen without adding it the drawer screens?
Or Can I hide profile item from drawer items?
To hide a menu item from drawer, use Array.map(...) instead of <DrawerItemList {...props} /> in custom drawer content.,
{drawerItems.map((item, index) => {
return (
<DrawerItem
label={item.drawerLabel}
onPress={() => props.navigation.navigate(item.routeName)}
/>
);
})}
and add a useEffect hook to custom drawer content like below,
let [drawerItems, setDrawerItems] = useState([]);
useEffect(() => {
let drawerItemsList = [];
for (const key in props.descriptors) {
if (props.descriptors.hasOwnProperty(key)) {
if (!key.includes('profile')) {
const element = props.descriptors[key];
element.options.routeName = key.substring(0, key.indexOf('-'));
drawerItemsList.push(element.options);
}
}
}
setDrawerItems(drawerItemsList);
}, []);
Another approach.,
Create an Array like below in the custom drawer content.,
const drawerItemsList = [
{
drawerLabel: 'Products',
drawerIcon: 'product',
routeName: 'products',
active: true,
},
{
drawerLabel: 'Orders',
drawerIcon: 'order',
routeName: 'orders',
active: false,
},
];
let [drawerItems, setDrawerItems] = useState(drawerItemsList);
and instead of <DrawerItemList {...props} /> use <Flatlist /> like below.,
<View>
<FlatList
data={drawerItems}
keyExtractor={(item)=>item.routeName.trim()}
renderItem={({item,index})=>(
<DrawerItem
label={item.drawerLabel}
icon={({color, size}) => <Ionicons name={item.drawerIcon} color={item.active?'#1e90ff':'#ccc'} size={size} />}
labelStyle={[item.active?{color: '#1e90ff'}:{color: '#ccc'}]}
style={item.active?{backgroundColor: '#1e90ff20'}:null}
onPress={() => {
drawerItemsList.forEach((element,i) => {
i!==index?element.active=false:element.active=true
});
setDrawerItems(drawerItemsList)
props.navigation.navigate(item.routeName)
}}
/>
)}
/>
</View>

how to render conditionally within the react native stack navigator header?

I'm trying to render the headerRight conditionally based on a navigation param. I am currently trying this in the static navigationOptions. Here is my code but nothing is rendering to the screen
static navigationOptions = ({navigation}) => ({
headerRight : () => {
if (navigation.state.params.user.following) {
return (
<TouchableOpacity
onPress={() => this.followUser()}>
<Icon2 name="ios-person-add-outline" size={35} />
</TouchableOpacity>
)} else {
return (
<TouchableOpacity
onPress={() => this.unfollowUser()}>
<Icon name="user-times" size={20} />
</TouchableOpacity>
)}
},
})
Can this be done or will I need to use a custom header here?
Any help would be hugely appreciated! Thanks!
Solution:
remove the anonymous function and implement the conditional syntax recommended by soutot
static navigationOptions = ({navigation}) => ({
headerRight : navigation.state.params.otherUser.following ?
( <TouchableOpacity
onPress={() => this.followUser()}>
<Icon2 name="ios-person-add-outline" size={35} />
</TouchableOpacity> )
:
( <TouchableOpacity
onPress={() => this.unfollowUser()}>
<Icon name="user-times" size={20} />
</TouchableOpacity> )
})
You are using a comma (,) after your 'else' statement. Also you can try something like this
return(
navigation.state.params.user.following ?
<TouchableOpacity
onPress={() => this.followUser()}>
<Icon2 name="ios-person-add-outline" size={35} />
</TouchableOpacity>
:
<TouchableOpacity
onPress={() => this.unfollowUser()}>
<Icon name="user-times" size={20} />
</TouchableOpacity>
);
For more info about conditional rendering, check the following docs:
https://facebook.github.io/react/docs/conditional-rendering.html
https://facebook.github.io/react/docs/conditional-rendering.html#inline-if-else-with-conditional-operator
Hope it helps