Center Text in FlatList next to Icon - React Native - react-native

I am currently trying to center the text from the FlatList.
By centering I mean I want it to be in the middle, right of each Icon.
Currently this is how is displaying, it's on the bottom. I just want it to be a little bit higher:
Here is how my component looks like:
I have tried to implement few styles, but still no success.
The thing that crossed my mind but did not try was to hard code each line and drop the loop, but I am not sure if this is right to do.
import SocialIcon from 'react-native-vector-icons/AntDesign';
import BookingIcon from 'react-native-vector-icons/FontAwesome';
import FeatherIcons from 'react-native-vector-icons/Feather';
export const bookIcon = (<BookingIcon name="pencil-square-o" size={40} color="purple" />);
export const calendarIcon = (<SocialIcon name="calendar" size={40} color="purple" />);
export const questionIcon = (<SocialIcon name="questioncircleo" size={40} color="purple" />);
export const externalLinkIcon = (<FeatherIcons name="external-link" size={40} color="purple" />);
class AboutMe extends Component {
static navigationOptions = {
title: "About Me",
}
render() {
return (
<View style={styles.container}>
<View style={styles.topBox}>
<View style={styles.circleOuter} />
<View style={styles.circle} />
</View>
<View style={styles.middleBox}>
</View>
<View style={styles.bottomBox}>
<FlatList
contentContainerStyle={styles.listItem}
data={[
{key: 'Book a free appointment', page:'Book', icon: bookIcon},
{key: 'Availability', page:'Availability', icon:calendarIcon},
{key: 'FAQ', page:'Faq', icon: questionIcon},
{key: 'Useful Links', page: 'Links', icon: externalLinkIcon},
]}
onPress={() => this.props.navigation.navigate('Book')}
renderItem={({item}) => {
return (
<TouchableHighlight onPress={() => this.props.navigation.navigate(`${item.page}`)}>
<Text >{item.icon}{item.key}</Text>
</TouchableHighlight>
)
}}
/>
</View>
</View>
);
};
};
const styles = StyleSheet.create({
container: {
flex: 1
},
topBox: {
flex:3,
backgroundColor: 'red',
justifyContent:'center',
alignItems: 'center'
},
middleBox: {
flex:1,
backgroundColor: 'yellow'
},
bottomBox: {
flex:4,
backgroundColor: 'orange',
padding: 20
},
circle: {
width: 160,
height: 160,
borderRadius: 160/2,
backgroundColor: 'green',
position: 'absolute'
},
circleOuter: {
width: 180,
height: 180,
borderRadius: 180/2,
backgroundColor: 'black'
},
listItem: {
flex:1,
justifyContent: 'center'
},
text: {
fontSize: 20,
}
});

You need to wrap the Text tag in a View/TouchableHighlight tag and then center the text tag vertically. Try this and let me know. It could be necessary that you wrap the icons in a separated image tag. if the code avode dont work means that a separeted tag is necessary so let me know!
<TouchableHighlight
style={styles.buttonsStyle}
onPress={() => this.props.navigation.navigate(`${item.page}`)}
>
<Text>{item.icon}{item.key}</Text>
</TouchableHighlight>
...
...
...
//in the styles add
buttonsStyle:{
justifyContent: 'center',
}
EDIT1
In order to wrap the icons it should be like following.. Note that you cannot use TouchableHighlight in this case. it seems to be a bug with react-native. aslo i used TouchableOpacity
renderItem={({item}) => {
return (
<TouchableOpacity
style={styles.buttonsStyle}
onPress={() => this.props.navigation.navigate(`${item.page}`)}
>
<Image style={styles.imgStyles} source={item.icon} />
<Text style={styles.mappedTextStyle}>{item.key}</Text>
</TouchableOpacity>
)
}}
styles to change/add
buttonsStyle:{
alignItems: 'center',
flexDirection:'row',
marginTop: 5,
},
imgStyles:{
width: 40,
height: 40,
marginRight: 10
},
mappedTextStyle: {
fontSize: 18,
color: 'black'
},
EDIT 2
In order to cover vector-icons lib, i have created a Expo snack for producing the desired behavior. Expo snack has also the expected solution for the problem Expo Snack

Related

Navigation With Flatlist Data in React Native

Hello Here i have some data as the form of Flatlist and i have extracted it, now i want to move on that
screen that i have clicked on example
if i clicked on screen A then i will moved to screen A,
if i clicked on screen B then i will moved on screen B,
if i clicked on screen C then i will moved to screen C,
if i clicked on screen D then i will moved on screen D, And
Show their Header Also
How to call proper screen according to their header and screen..
How to Navigate it..
Sample image here
Code Here..
import React, {useState} from 'react';
import {
FlatList,
Image,
View,
Text,
SafeAreaView,
StyleSheet,
TouchableOpacity
} from 'react-native';
import App1 from './App1';
const dummyArray = [
{id: '1', value: 'A',exdate: '2020', City: 'Delhi'},
{id: '2', value: 'A',exdate: '2019',City: 'Mumbai'},
{id: '3', value: 'C',exdate: '2015 ',City: 'Indore'},
{id: '4', value: 'D',exdate: '2016',City: 'Patna'},
{id: '5', value: 'E',exdate: '2000',City: 'Raipur'},
];
const Home = ({ navigation }) => {
const [listItems, setListItems] = useState(dummyArray);
function handlePick(item){
}
const ItemView = ({item}) => { //flatlist data view
return (
// FlatList Item
<View style={styles.itemView}>
<TouchableOpacity style={styles.button} activeOpacity={.5}
onPress={()=>handlePick(item)}>
<View style={styles.stateView}>
<Text style={styles.textItem} onPress={() => getItem(item)}>
{item.value}
</Text>
<Image source={require('./right.jpg')} style={{marginLeft: 70, marginTop: 5,width: 30, height: 30}} />
</View>
<View
style={{
marginTop: 3,
height: 1,
width: '100%',
backgroundColor: '#C8C8C8'
}}
/>
<Text style={styles.text}>Date{"\t\t\t\t"}{item.exdate}</Text> //flatlist Data
<Text style={styles.capitalText}>Capital City{"\t\t\t\t\t\t"}{item.City}</Text> //flatlistCity
</TouchableOpacity>
</View>
);
};
const ItemSeparatorView = () => {
return (
// FlatList Item Separator
<View
style={{
backgroundColor: '#C8C8C8'
}}
/>
);
};
};
return (
<SafeAreaView style={{flex: 1}}>
<View style={styles.container}>
<FlatList
data={listItems}
ItemSeparatorComponent={ItemSeparatorView}
renderItem={ItemView}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
flex: 1,
marginLeft: 10,
marginRight: 10,
marginBottom: 10,
},
textItem: {
marginTop: 5,
fontSize: 18,
flexDirection: 'row',
fontWeight: 'bold',
height: 20,
width: 250,
},
itemView: {
height: 150,
padding: 10,
margin: 8,
backgroundColor: '#fff'
},
stateView:{
height: 40,
flexDirection: 'row',
},
text:{
marginTop: 5,
width: 300,
height: 28
},
});
export default Home;
Please Suggest any solution..
Thanks..
Try this way
function handlePick(item){
const route = `Screen${item.value}`; // dynamic screen like 'ScreenA' or 'ScreenB' etc...
navigation.navigate(route, {data: item} ); This way will navigate to route with data object of item
}

Know which element was touched with React Native's PanResponder?

Im making a drag and drop with the PanResponder but I only want part of a component to be the 'target' which initiates the drag. Many elements are contained within a ScrollView, and dragging on the elements outside of the 'target' should scroll as usual.
const Dragger = () => {
return (
<View {...panResponder.panHandlers}>
<View style={{ flexDirection: 'row' }}>
<Text>Drag me</Text>
<Text>Im not draggable</Text>
</View>
<View style={{ flexDirection: 'row' }}>
<Text>Drag me</Text>
<Text>Im not draggable</Text>
</View>
</View>
)
}
const Parent = () => {
return(
<ScrollView>
<Text>Stuff</Text>
<Dragger />
<Text>Stuff</Text>
<ScrollView/>
)
}
Can this be done or do I need to attach multiple panHandlers to each <Text>Drag me</Text>?
From the docs I see there is a nativeEvent.target which returns "The node id of the element receiving the touch event", however it's just a number so Im not sure how to use it?
Would I need to find out the node IDs of the <Text>Drag me</Text> elements and see if the number that came back is in that list?
UPDATE: Here is a more visual demo of what Im trying to do:
https://snack.expo.io/#jamesweblondon/rude-pretzel
I need PanResponder drag events on the grey boxes, but not on the text inputs:
import React from "react";
import { StyleSheet, Text, View, TextInput } from "react-native";
const items = new Array(50).fill(0).map((item, index) => {
return {
id: index,
backgroundColor: `rgb(${Math.floor(Math.random() * 255)}, ${
index * 5
}, ${132})`,
};
});
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
item: {
display: "flex",
flexDirection: "row",
height: 200,
width: "100%",
justifyContent: "space-around",
alignItems: "center",
},
input: {
color: "white",
fontSize: 20,
height: "100%",
flex: 1,
},
handle: {
display: "flex",
backgroundColor: "grey",
height: "80%",
width: 100,
marginHorizontal: 20,
},
});
export default function App() {
return (
<View style={styles.container}>
{items.map((item) => {
return (
<View
style={[styles.item, { backgroundColor: item.backgroundColor }]}
>
<View style={styles.handle} />
<TextInput style={styles.input} defaultValue={item.id} />
</View>
);
})}
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
You started your question with some snippets that I couldn't find in the link you posted, so I started from that and created a fork.
So in order to get the PanResponder drag events on the grey boxes, but not on the text inputs you should do like this on your item component:
<View style={[styles.item, { backgroundColor: item.backgroundColor }]} >
<View style={styles.handle} {...panResponder.panHandlers} />
<TextInput style={styles.input}>{item.id}</TextInput>
</View>
For the PanResponder i used the default config from https://reactnative.dev/docs/panresponder#example
Here's an update on your code to try it.
Hope this helps! Tell me if this isn't working for you.

Issue making model pop up onPress of flatlist

I have a flatlist of cards, and I want a modal to appear when someone presses the card. Pressing the card doesn't seem to do anything though, so I'm wondering what I've done wrong. In my code at the top I have defined the state for the visibility of the modal, if you scroll down to the card you'll see onPress changes the state. Below the card is the actual modal which uses the state of the visible property to display it or not.
Code:
class HomeScreen extends React.Component {
state = {
isModalVisible: false
};
toggleModal = () => {
this.setState({ isModalVisible: !this.state.isModalVisible });
};
render() {
return (
<View style = {{flex:1}}>
<Header
centerComponent={{ text: 'MY MACROS', style: { color: '#fff', letterSpacing: 2} }}
containerStyle={{
backgroundColor: '#5BC0EB',
}}
/>
<Progress.Bar progress={0.7} width={null} height={10} borderRadius = {0} color = {'lightgreen'}/>
<ScrollView>
<FlatList
data = {Macros}
renderItem = {({ item }) => (
<TouchableOpacity>
<Card style = {{justifyContent: 'center', margin: 1, backgroundColor: '#ffff', borderRadius: 25}} onPress = {() => {this.toggleModal}}>
<Card.Content>
<View style = {{flexDirection: 'row', justifyContent: 'space-between'}}>
<View style = {{flexDirection: 'column', justifyContent: 'space-between'}}>
<Title style = {{paddingTop: 20, fontSize: 35, fontWeight: 'bold',color: 'black', letterSpacing: 2}}>{item.total} {item.unit}</Title>
<Text style= {{fontSize: 30, color: 'black', letterSpacing: 2, fontWeight: '100'}}>{item.title}</Text>
</View>
<MainProgress/>
</View>
</Card.Content>
<Card.Actions>
</Card.Actions>
</Card>
<Modal isVisible = {this.state.isModalVisible}>
<View>
<Text>Test</Text>
<Button title = "Cancel" onPress = {this.toggleModal}/>
</View>
</Modal>
</TouchableOpacity>
)}
keyExtractor = {item => item.key}
/>
</ScrollView>
<Button color = {'#5BC0EB'} onPress={popUpForm}>Add New Macro</Button>
</View>
);
}
}
According to your code, you need to pass your toggleModal function to TouchableOpacity in order to display your Model. Check below sample for more information.
import React, { Component } from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text, TouchableOpacity, Modal, Button } from 'react-native';
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
export default class App extends Component {
state = {
isModalVisible: false
}
toggleModal = () => {
this.setState({
isModalVisible: !this.state.isModalVisible
});
};
renderItem = ({ item }) => (
<TouchableOpacity style={styles.item} onPress={this.toggleModal}>
<Text style={styles.title}>{item.title}</Text>
</TouchableOpacity>
)
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={this.renderItem}
keyExtractor={item => item.id}
/>
{
this.state.isModalVisible &&
<Modal
visible={this.state.isModalVisible}
transparent={true}
animationType='slide'
onRequestClose={this.toggleModal}
>
<View style={styles.modelStyle}>
<View style={styles.modelWrapperStyle}>
<Text>Test</Text>
<Button title="Cancel" onPress={this.toggleModal} />
</View>
</View>
</Modal>
}
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 50,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
modelStyle: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)'
},
modelWrapperStyle: {
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ffffff',
padding: 20,
width: '90%'
}
});
Change this according to your requirement.
Hope this helps you. Feel free for doubts.

How to open a facebook, instagram.. (social network) profile from my app

I'm creating an application using react native and I need to allow user to open all the available social networks of another user.
I saw that question and this one, but they doesn't works for me.
can anyone help
EDIT
I know how to create icons and call social networks' website, however, what I want is to open a user profile in a social networks app
I remarked that for instagram, the user profile url, opens the app, howover for Fb, it opens the website,
This following is used in my project. Its the contact US page of my react native app.
Works fine for me.
import React, { Component } from 'react';
import { StyleSheet, Text, Dimensions, View, TouchableNativeFeedback, TouchableOpacity, Image, Linking, ScrollView, Platform } from 'react-native';
import { Icon, Card, CardItem } from 'native-base';
import Colors from '../config/Colors';
import Dimens from '../config/Dimens';
import { RNToasty } from 'react-native-toasty';
import OneSignal from 'react-native-onesignal';
import { getStatusBarHeight } from 'react-native-status-bar-height';
import { colors } from 'react-native-elements';
import { Header } from 'react-navigation';
import HeaderBackground from '../components/HeaderBackground';
var width = Dimensions.get('window').width;
var height = Dimensions.get('window').height;
class SocialMedia extends Component {
constructor(props) {
super(props);
}
static navigationOptions = ({ navigation }) => {
return {
header: (props) => <HeaderBackground {...props} />,
headerStyle: {
backgroundColor: Colors.transparent,
paddingTop: Platform.OS === 'ios' ? 0 : getStatusBarHeight(),
height: Header.HEIGHT + (Platform.OS === 'ios' ? 0 : getStatusBarHeight()),
},
title: 'Social Media',
headerTintColor: Colors.white,
headerTitleStyle: {
fontWeight: 'bold',
padding: 5,
paddingTop: 10
},
headerMode: 'float',
headerLeft: <Icon
onPress={() => navigation.goBack()}
name="arrow-back"
type='MaterialIcons'
style={{ color: 'white', marginLeft: 10, padding: 5, paddingTop: 10 }}
/>,
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.cardContainer}>
<TouchableOpacity background={TouchableNativeFeedback.Ripple(Colors.secondaryColor, false)} onPress={() => { Linking.openURL('https://www.facebook.com/max/') }}>
<Card style={styles.card}>
<CardItem style={styles.cardBody}>
<Image source={require('../assets/icons/Contact_Facebook.jpg')} style={styles.icon} resizeMode='contain' />
<Text style={styles.iconText}>Facebook</Text>
</CardItem>
</Card>
</TouchableOpacity>
<TouchableOpacity background={TouchableNativeFeedback.Ripple(Colors.secondaryColor, false)} onPress={() => { Linking.openURL('https://www.instagram.com/max/') }}>
<Card style={styles.card}>
<CardItem style={styles.cardBody}>
<Image source={require('../assets/icons/Contact_Insta.jpg')} style={styles.icon} resizeMode='contain' />
<Text style={styles.iconText}>Instagram</Text>
</CardItem>
</Card>
</TouchableOpacity>
<TouchableOpacity background={TouchableNativeFeedback.Ripple(Colors.secondaryColor, false)} onPress={() => { Linking.openURL('https://www.youtube.com/channel/UCnQoipGmBRC1XTOUY8c1UdA') }}>
<Card style={styles.card}>
<CardItem style={styles.cardBody}>
<Image source={require('../assets/icons/Contact_YT.jpg')} style={styles.icon} resizeMode='contain' />
<Text style={styles.iconText}>YouTube</Text>
</CardItem>
</Card>
</TouchableOpacity>
<TouchableOpacity background={TouchableNativeFeedback.Ripple(Colors.secondaryColor, false)} onPress={() => { Linking.openURL('https://max.com/') }}>
<Card style={styles.card}>
<CardItem style={styles.cardBody}>
<Image source={require('../assets/icons/Contact_web.jpg')} style={styles.icon} resizeMode='contain' />
<Text style={styles.iconText}>Website</Text>
</CardItem>
</Card>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 8
},
contentContainer: {
paddingBottom: 20
},
cardContainer: {
flex: 1,
padding: 5,
width: '100%',
},
card: {
padding: 5,
height: height * .20,
width: '100%',
backgroundColor: '#fff',
flexDirection: 'column',
//alignItems: 'center',
//justifyContent: 'center',
shadowColor: '#1A9EAEFF',
shadowOffset: { width: 3, height: 3 },
shadowOpacity: 3,
shadowRadius: 2,
elevation: 10,
borderRadius: 5,
overflow: 'hidden'
},
cardBody: {
flex: 1,
flexDirection: 'row',
},
iconText: {
flex: 1,
fontWeight: 'bold',
alignItems: 'center',
justifyContent: 'center',
fontSize: 18,
color: '#1A9EAEFF'
},
icon: {
flex: 1,
width: '100%',
height: width * .18,
},
});
export default SocialMedia;
Hope this helps..
You're good to go!!
For instagram this is working for me,
Linking.openURL('https://www.instagram.com/profile_username/');
for facebook its just opening the facebook app.
Linking.openURL('fb://profile_username/');

how to display buttons under a scrollview in react native

good day everyone,
i'm working on this react-native project and i got a problem with the scrollView component and buttons positions. so basically i want to have 2 buttons, to either confirm or cancel my choice from the scrollView, underneath the scrollview and each one is filling half the width. both the buttons and the scrollview are found inside a modal.
i have tried every combination of flexbox and heights i managed to think of but nothing worked and the height of the section including the buttons is still way bigger than i want and buttons are not side by side.
this the component with the problem:
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Modal, TouchableHighlight, ScrollView, FlatList } from 'react-native';
import { NavigationActions } from "react-navigation";
import genericStyle from '../../styles/generic-style';
import { colors, fontSizes } from '../../styles/base';
import values from '../../styles/responsive';
import NAVLogo from '../generic/NAVLogo';
export default class Welcome extends Component {
state = {
modalVisible: false,
values: [
{
id: 1,
text: "one"
},
{
id: 2,
text: "two"
},
{
id: 3,
text: "three"
},
{
id: 4,
text: "four"
},
{
id: 5,
text: "five"
},
{
id: 6,
text: "six"
},
{
id: 7,
text: "seven"
},
]
};
setModalVisible(visible) {
this.setState({ modalVisible: visible });
}
render() {
return (
<View style={[styles.welcome, genericStyle.centerContainer]}>
<Modal
animationType="slide"
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.modal}>
<View style={styles.modalContent}>
<View style={styles.scrollViewStyle}>
<ScrollView style={styles.scrollViewStyle}>
{this.state.values.map((value, index) => (
<TouchableHighlight
onPress={() => console.log("TH1...")}
style={styles.company}
key={value.id}
>
<Text>{value.text}</Text>
</TouchableHighlight>
))}
</ScrollView>
</View>
<View
style={{
flex: 1,
flexDirection: "column",
height: "15%"
}}
>
<TouchableOpacity
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}
>
<Text>confirm</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}
>
<Text>cancel</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
<NAVLogo />
<Text style={styles.text}>
Welcome
<Text style={styles.uname}>
{" " + this.props.navigation.getParam("uname", "Unknown")}
</Text>
</Text>
<TouchableOpacity
onPress={() => {
console.log("company");
this.setModalVisible(true);
}}
style={styles.btnContainer}
>
<View style={styles.btn}>
<Text style={styles.btnText}>Select Company</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
console.log("log out");
this.props.navigation.dispatch(
NavigationActions.navigate({
routeName: "Home"
})
);
}}
style={styles.btnContainer}
>
<View style={styles.btn}>
<Text style={styles.btnText}> Log out </Text>
</View>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
welcome: {
backgroundColor: colors.sky
},
btn: {
width: "75%",
paddingVertical: 15,
backgroundColor: colors.darksky,
marginTop: values.mtb + 3,
alignItems: "center"
},
btnText: {
fontSize: values.fontSize + 2,
color: colors.light
},
btnContainer: {
width: "100%",
alignItems: "center"
},
text: {
fontSize: values.fontSize,
color: colors.dark,
fontWeight: "400",
marginVertical: 20
},
uname: {
fontWeight: "900",
fontSize: values.fontSize + 2
},
modalContent: {
width: "80%",
backgroundColor: colors.light,
flex: 0
},
modal: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(00,00,00,0.3)"
},
company: {
width: "100%",
borderBottomColor: colors.dark,
borderBottomWidth: 1,
paddingLeft: 35,
paddingVertical: 30
},
scrollViewStyle: {
flexGrow: 0,
flex: 0,
height: "85%"
}
});
this is the way the modal is displayed (i haven't worked that much on styling since i was stuck with positioning the buttons for the past 2 hours):
i hope someone can help me out with this. i'm new to react native so i'm pretty sure this is a trivial issue that i missed somewhere.
thanks to everyone in advance for the their time and help.
use flexDirection:'row' to make it side by side, and position:'absolute' to make it stay at the bottom
<View
style={{
position:'absolute',
bottom:10,
flexDirection: "row",
justifyContent:'space-between',
width:'100%'
}}>
<TouchableOpacity>
<Text> CONFIRM </Text>
</TouchableOpacity>
<TouchableOpacity>
<Text> CANCEL </Text>
</TouchableOpacity>
</View>