How to implement modal swipe to down like instagram? - react-native

I'm currently working on an React Native project. I need to implement a feature similar to "Swipe Down To close Modal" on Instagram

I believe that you're using #react-native-community/react-native-modal package. In the library documents, you can see that there is a property called swipeDirection which is either a string or an array that can be one or many of the following options; 'up', 'down', 'left' or 'right.
You can also set the threshold required swipe action to be completed by using swipeThreshold property. The default is 100 according to the library documents.
Here's an example of the modal;
import React from 'react';
import {View, Text} from 'react-native;
import Modal from 'react-native-modal';
const ModalComponent = props => {
const [isVisible, setIsVisible] = useState(true);
return (
<Modal isVisible={isVisible}
swipeDirection="down"
//swipeDirection={["up", "down", "left", "right"]}
onSwipeComplete={(e) => { setIsVisible(false); })
style={{ justifyContent: 'flex-end', margin: 0, }} >
<View style={{ backgroundColor: 'steelblue' }}>
<Text>Hello Modal</Text>
</View>
</Modal>
);
};
export {ModalComponent};

Related

I am trying to implement bottom sheet in react native with npm package reanimated-bottom-sheet but swipe down gesture handler is not working

import statements
import * as React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import Animated from 'react-native-reanimated';
import BottomSheet from 'reanimated-bottom-sheet';
main app function
export default function App() {
const renderContent = () => (
<View
style={{ backgroundColor: 'white', padding: 16, height: 450, }} >
<Text>Swipe down to close</Text>
</View>
const sheetRef = React.useRef(null);
const fall = new Animated.Value(1)
return (
<>
<View
style={{
flex: 1,
backgroundColor: 'papayawhip', alignItems: 'center', justifyContent: 'center',
}}
>
<Button title="Open Bottom Sheet" onPress={() => sheetRef.current.snapTo(0)} />
</View>
continue with bottom sheet code
<BottomSheet
ref={sheetRef}
snapPoints={[200, 0]}
initialSnap={1} borderRadius={20}
renderContent={renderContent}
callbackNode={fall}
enabledGestureInteraction={true}
/>
</>
)
}
I have set enabledGestureInteraction to true but still it is not working
I haven't used reanimated-bottom-sheet before. But looks like there is a problem with snapPoints property. It should be:
snapPoints={[0, 200]}
The package is out of date. I suggest you use this one instead: https://gorhom.github.io/react-native-bottom-sheet/
I'm using it in my project. It's awesome.
The solution I found for this is we have to wrap our components inside GestureHandlerRootView compnent from react-native-gesture-handler and we have to set it's style with flex:1
discussion ref link - https://github.com/gorhom/react-native-bottom-sheet/issues/775

React-native-flash-message getting under the Card

I am using react-native-flash-message https://www.npmjs.com/package/react-native-flash-message.
Everything works fine as it is easy to use them. But the problem is when i used it with the Card component (from react-native-paper), the message hides under the card. I want the message to be on the top of everything.
I tried zIndex But it doesnot work.
Here is the demo code;
import * as React from 'react';
import { View, ScrollView } from 'react-native';
import { Avatar, Button, Card, Title, Paragraph } from 'react-native-paper';
import FlashMessage from 'react-native-flash-message';
import { showMessage } from 'react-native-flash-message';
const LeftContent = (props) => <Avatar.Icon {...props} icon="folder" />;
const show = () => {
showMessage({
message: 'This is a message',
});
};
const MyComponent = () => (
<View style={{justifyContent: 'center', marginTop: 30}}>
<Card style={{ margin: 30 }} elevation={30}>
<ScrollView contentContainerStyle={{justifyContent: 'center', marginTop: 30}}>
<Card.Title
title="Card Title"
subtitle="Card Subtitle"
left={LeftContent}
/>
<Card.Content>
<Title>Card title</Title>
<Paragraph>Card content</Paragraph>
</Card.Content>
<Card.Cover source={{ uri: 'https://picsum.photos/700' }} />
<Card.Actions>
<Button onPress={() => show()}>show message</Button>
</Card.Actions>
</ScrollView>
</Card>
<FlashMessage style={{ marginTop: 20 }} position="top" />
</View>
);
export default MyComponent;
Note that this problem only occurs on android devices. On ios, it works fine.
Though i found a solution. Putting <FlashMessage style={{ marginTop: 20 }} position="top" /> inside the card component will resolve it, but i have enabled FlashMessage globally, so i want to change it globally and don't want to put it in every card component
So after some search, i found that though the react-native-flash-message is not made in that way to be rendered on top of everything like card, modals or dialog.
So one way to solve it (infact, i think this is the only way) would be to wrap the FlashMessage component in card and give it some high elevation (say 1000). Note that the elevation provided to it should by the largest among all cards used.

How do I paginate in React Native Paper DataTable?

I'm having trouble finding enough information to use React Native Paper DataTable Pagination. The documents are pretty slim and there are only a few videos on the topic that haven't given me the information I need.
import 'react-native-gesture-handler';
import React, { useEffect, useState } from 'react';
import { View, Text, Button, TextInput, ActivityIndicator } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer'
import { DataTable, page, setPage, setItemsPerPage, optionsPerPage, itemsPerPage } from 'react-native-paper';
const Drawer = createDrawerNavigator();
function SearchComponent() {
return (
<View style={{ flex: 1 }}>Search Bar</View>
);
}
function TableComponent({ headers, values }) {
if (!headers || !values) return null;
const optionsPerPage = [0];
const [page, setPage] = useState(0);
const [itemsPerPage, setItemsPerPage] = useState(optionsPerPage[10]);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<DataTable.Row style={{ width: 1000 }}>
<DataTable.Cell text>First Name</DataTable.Cell>
<DataTable.Cell text>Last Name</DataTable.Cell>
<DataTable.Cell text>Provider Email</DataTable.Cell>
<DataTable.Cell text>Review</DataTable.Cell>
<DataTable.Cell text>Rating</DataTable.Cell>
<DataTable.Cell text>Review Completed</DataTable.Cell>
</DataTable.Row>
<DataTable style={{ width: 1000 }}>
{/* {headers?.map(({ title, numeric }) => <DataTable.Title key={title} numeric={numeric}>{title}</DataTable.Title>)} */}
{values?.map((value, index) => <DataTable.Row key={index}>
{headers?.map(({ title }) => <DataTable.Cell key={title}>{value[title]}</DataTable.Cell>)}
</DataTable.Row>)}
<DataTable.Pagination
page={page}
numberOfPages={1000}
onPageChange={(page) => setPage(page)}
label="1-2 of 1000"
optionsPerPage={optionsPerPage}
itemsPerPage={itemsPerPage}
setItemsPerPage={setItemsPerPage}
optionsLabel={'Rows per page'}
/>
</DataTable>
</View>
);
}
I've been messing with numbers in the DataTable.Pagination component, but nothing I change has any visual effect. I could really use someone experienced with React Native Paper to explain it to me, please.
This is because there is no prop under DataTable.Pagination that deals with the rows. DataTable.Pagination handles the data for pagination only, nothing to do with the rows. Displaying the rows is handled by DataTable.Rows. This is were you need to filter the data before mapping it out for display.
I'm guessing this one handles displaying the rows in your code.
{values?.map((value, index) => <DataTable.Row key={index}>
{headers?.map(({ title }) => <DataTable.Cell key={title}>{value[title]}</DataTable.Cell>)}
</DataTable.Row>)}
Filter/segregate the values first using slice before mapping it out for display. You may use code like this.
values.slice(page * itemsPerPage, page * itemsPerPage + itemsPerPage).map((value) => <DataTable.Row key={index}>{headers?.map(({ title }) => <DataTable.Cell key={title}>{value[title]}</DataTable.Cell>)}</DataTable.Row>)})
I cant test this works on your code since you did not provide a sandbox but I made a sample using the data provided in react native paper. See working example here : Data pagination sample

How to translate mobile app text using language drop-down inside react-native app?

I want to add translate drop-down inside mobile app to translate the app text without using language json file.
I just want to add the select list at the top of app to change the language of text, like this: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_google_translate
Is this possible with react native app?
Here is an example of how you can achieve that.
Working Example: Expo Snack
import React, { useState } from 'react';
import { Text, View, StyleSheet, Picker } from 'react-native';
import Constants from 'expo-constants';
const engToHindi = {
english: 'hello',
hindi: 'नमस्कार',
};
export default function App() {
const [language, setLanguage] = useState('english');
return (
<View style={styles.container}>
<Picker
selectedValue={language}
style={{ height: 50, width: 100 }}
onValueChange={(itemValue) => setLanguage(itemValue)}>
<Picker.Item label="English" value="english" />
<Picker.Item label="हिन्दी" value="hindi" />
</Picker>
<Text>{engToHindi[language]}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
Online Implementation using Google Translate API would be possible but I don't have the API keys so could not give you the example of that implementation.

setNativeProps Change Value for Text Component React Native Direct Manipulation

I want to directly update the value of a component due to performance reasons.
render(){
<View>
<Text style={styles.welcome} ref={component => this._text = component}>
Some Text
</Text>
<TouchableHighlight underlayColor='#88D4F5'
style={styles.button}>
<View>
<Text style={styles.buttonText}
onPress={this.useNativePropsToUpdate.bind(this)}>
Iam the Child
</Text>
</View>
</TouchableHighlight>
</View>
}
This is the method I use to update the text component. I dont know if I am setting the right attribute/ how to figure out which attribute to set:
useNativePropsToUpdate(){
this._text.setNativeProps({text: 'Updated using native props'});
}
Essentially trying to follow the same approach from this example:
https://rnplay.org/plays/pOI9bA
Edit:
When I attempt to explicitly assign the updated value:
this._text.props.children = "updated";
( I know this this the proper way of doing things in RN ). I get the error "Cannot assign to read only property 'children' of object'#'"
So maybe this is why it cant be updated in RN for some reason ?
Instead of attempting to change the content of <Text> component. I just replaced with <TextInput editable={false} defaultValue={this.state.initValue} /> and kept the rest of the code the same. If anyone know how you can change the value of <Text> using setNativeProps OR other method of direct manipulations. Post the answer and ill review and accept.
The text tag doesn't have a text prop, so
this._text.setNativeProps({ text: 'XXXX' })
doesn't work.
But the text tag has a style prop, so
this._text.setNativeProps({ style: { color: 'red' } })
works.
We can't use setNativeProps on the Text component, instead, we can workaround and achieve the same result by using TextInput in place of Text.
By putting pointerEvent='none' on the enclosing View we are disabling click and hence we can't edit the TextInput (You can also set editable={false} in TextInput to disbale editing)
Demo - Timer (Count changes after every 1 second)
import React, {Component} from 'react';
import {TextInput, StyleSheet, View} from 'react-native';
class Demo extends Component {
componentDidMount() {
let count = 0;
setInterval(() => {
count++;
if (this.ref) {
this.ref.setNativeProps({text: count.toString()});
}
}, 1000);
}
render() {
return (
<View style={styles.container} pointerEvents={'none'}>
<TextInput
ref={ref => (this.ref = ref)}
defaultValue={'0'}
// editable={false}
style={styles.textInput}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 0.7,
justifyContent: 'center',
alignItems: 'center',
},
textInput: {
fontSize: 60,
width: '50%',
borderColor: 'grey',
borderWidth: 1,
aspectRatio: 1,
borderRadius: 8,
padding: 5,
textAlign: 'center',
},
});
export default Demo;
As setNativeProps not solving the purpose to alter the content of <Text />, I have used below approach and is working good. Create Simple React Component like below...
var Txt = React.createClass({
getInitialState:function(){
return {text:this.props.children};
},setText:function(txt){
this.setState({text:txt});
}
,
render:function(){
return <Text {...this.props}>{this.state.text}</Text>
}
});