Related
I need to show different tags depending on which user is logged.
Franchisee will see: 'Central' 'Empleados' 'Clientes'.
Employee: 'Store' 'Clientes'
User: none. just the generic info.
Here is my code:
(this is the array that states the scrollview)
const Chats = (props) => {
const TAGS = [
"store",
"Clientes",
"Central",
"Empleados",
]
and this is the component:
import React, { useState } from "react";
import { StyleSheet, FlatList, TouchableOpacity, ScrollView, Image } from 'react-native';
import { SimpleHeader, View, Text } from '../../elements/index';
const Chatstores = ({ chatsstore, navigation }) => (
<View>
<TouchableOpacity onPress={() => navigation.navigate("ChatPersonal")}>
<View style={styles.list} >
<Image source={chatsstore.img} style={styles.iconimg} />
<View style={styles.dataText}>
<View style={styles.nametime}>
<Text style={styles.text}>{chatsstore.name} </Text>
<Text >{chatsstore.time}</Text>
</View>
<Text style={styles.msg}>{chatsstore.msg} </Text>
</View>
</View>
</TouchableOpacity>
</View>
);
const ChatClients = ({ chatsClients, navigation }) => (
<View>
<TouchableOpacity onPress={() => navigation.navigate("ChatPersonal")}>
<View style={styles.list}>
<Image source={chatsClients.img} style={styles.iconimg} />
<View style={styles.dataText}>
<View style={styles.nametime}>
<Text style={styles.text}>{chatsClients.name} </Text>
<Text >{chatsClients.time}</Text>
</View>
<Text style={styles.msg}>{chatsClients.msg} </Text>
</View>
</View>
</TouchableOpacity>
</View>
);
const Chats = (props) => {
const { TAGS, chatsstore, chatsClients, navigation } = props;
const [selectedTag, setSelectedTag] = useState(null)
const [routeDistance, setRouteDistance] = useState(0);
return (
<View style={styles.wrapper}>
<SimpleHeader
style={styles.head}
titleLeft="Chats"
onSearchPress
onAddPress
/>
{/**shows horizontal, scrollview of Tags. */}
<View style={styles.scrollview}>
<ScrollView horizontal showsHorizontalScrollIndicator={false} >
<View style={styles.viewcontainer}>
{TAGS.map((tag) => (
<TouchableOpacity
onPress={() =>
setSelectedTag(tag === selectedTag ? null : tag)
}>
<View
style={[
styles.tag,
selectedTag === tag ? styles.selectedTag : {}
]}>
<Text style={styles.textTag}>{tag}</Text>
</View>
</TouchableOpacity>
))}
</View>
</ScrollView>
</View>
{/**If tag is store, shows its data, otherwise the rest */}
{selectedTag === "store" ? (
<View style={styles.chat}>
<FlatList
data={chatsstore}
renderItem={({ item, index }) => (
<Chatstores
chatsstore={item}
index={index}
navigation={navigation}
/>
)}
keyExtractor={(chatsstore) => chatsstore.name}
ListEmptyComponent={() => (
<Text center bold>No hay ningún mensaje de clientes</Text>
)}
/>
</View>
) :
<View style={styles.chat}>
<FlatList
data={chatsClients}
renderItem={({ item, index }) => (
<ChatClients
chatsClients={item}
index={index}
navigation={navigation}
/>
)}
keyExtractor={(chatsClients) => chatsClients.name}
ListEmptyComponent={() => (
<Text center bold>No hay ningún mensaje de clientes</Text>
)}
/>
</View>
}
</View>
);
};
const styles = StyleSheet.create({
wrapper: {
backgroundColor: "#ffffff",
display: "flex",
flex: 1,
},
head: {
height: 80,
display: "flex",
alignItems: "center",
zIndex: 1,
top: 5,
},
scrollview: {
display: "flex",
alignItems: "center",
justifyContent: "space-evenly",
},
viewcontainer: {
display: "flex",
flexDirection: "row",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 1,
right: 10,
},
list: {
bottom: 15,
flexWrap: "wrap",
alignContent: "space-between",
position: "relative",
marginVertical: 2,
backgroundColor: "#fff",
shadowColor: "#000",
elevation: 2,
flexDirection: "row",
}, dataText: {
alignSelf: "center",
flexDirection: "column",
width: "80%",
},
nametime: {
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
},
iconimg: {
display: "flex",
height: 43,
width: 43,
alignSelf: "center",
flexDirection: "column",
},
chat: {
margin: 10,
},
text: {
margin: 10,
fontFamily: "Montserrat_700Bold",
paddingHorizontal: 10,
},
msg: {
margin: 10,
fontFamily: "Montserrat_400Regular",
fontSize: 15,
paddingHorizontal: 10,
bottom: 10
},
map: {
display: "flex",
height: "100%",
},
tag: {
display: "flex",
alignSelf: "center",
marginBottom: 1,
width: 225,
padding: 10,
},
selectedTag: {
borderBottomColor: '#F5BF0D',
borderBottomWidth: 2,
},
textTag: {
fontFamily: "Montserrat_700Bold",
alignItems: "center",
textAlign: "center",
fontSize: 15,
},
buttonContainer: {
marginHorizontal: 20
},
button: {
backgroundColor: "#000000",
top: Platform.OS === 'ios' ? 12 : 20,
height: 60,
marginBottom: 40,
marginRight: 10,
},
});
export default Chats;
So I guess that in my "show horizontal tags" I should write some kind of if, that gets the role from the user token?
Or would it be better to write different routes into the navigation and handle it in 3 different components?
I am developing iOS apps in React Native Expo.
To display the image icon and placeholder in the Input column, I set it to Image icon and TextInput in the View.
When using KeyboardAvoidingView, the keyboard scrolls to the bottom of TextInput as shown in the attached image (1), but does anyone know if it is possible to scroll to the bottom of the description of the input field as shown in image (2)?
Image(1)
Image(2)
The article is based on the following.
https://reactnative.dev/docs/keyboardavoidingview
Parent function code.
<KeyboardAvoidingView behavior="padding" style={styles.containerStyle}>
<SafeAreaView style={styles.containerStyle}>
<ScrollView style={styles.containerStyle}>
<View style={styles.headContainerStyle}></View>
<View style={styles.mainContainerStyle}></View>
<View style={styles.headMessageContainerStyle}>
<Text style={styles.headMessageTextStyle}>Sign Up</Text>
</View>
{/* Email */}
<MailForm
inputAccessoryViewID={inputAccessoryViewID}
isCorrectMail={isCorrectMail}
setIsCorrectMail={setIsCorrectMail}
/>
{/* Password */}
<PasswordForm
inputAccessoryViewID={inputAccessoryViewID}
isCorrectPassewordSymbol={isCorrectPassewordSymbol}
setIsCorrectPassewordSymbol={setIsCorrectPassewordSymbol}
isCorrectPassewordStringCount={isCorrectPassewordStringCount}
setIsCorrectPassewordStringCount={setIsCorrectPassewordStringCount}
/>
{/* UserId */}
<UserIdForm
inputAccessoryViewID={inputAccessoryViewID}
isCorrectUserIdSymbol={isCorrectUserIdSymbol}
setIsCorrectUserIdSymbol={setIsCorrectUserIdSymbol}
isCorrectUserIdStringCount={isCorrectUserIdStringCount}
setIsCorrectUserIdStringCount={setIsCorrectUserIdStringCount}
isAvailableUserId={isAvailableUserId}
setIsAvailableUserId={setIsAvailableUserId}
/>
{/* Screen Bottom */}
<View style={styles.bottomStyle}>
{isCorrectMail && isCorrectPassewordSymbol && isCorrectPassewordStringCount && isCorrectUserIdSymbol && isCorrectUserIdStringCount && isAvailableUserId ?
(
<TouchableOpacity
style={styles.buttonContainerStyle}>
<Text style={styles.buttonTextStyle}>Sign Up</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
style={[styles.buttonContainerStyle, styles.buttonContainerInvalidStyle]}
onPress={() => navigation.navigate('SignUp')}>
<Text style={styles.buttonTextStyle}>Sign Up</Text>
</TouchableOpacity>
)}
<View style={styles.toLoginStyle}>
<Text style={styles.toLoginTextStyle}>Do you have an account?</Text>
<Text style={[styles.toLoginTextStyle, styles.toLoginTextLinkStyle]}>Login here</Text>
</View>
</View>
</ScrollView>
</SafeAreaView>
</KeyboardAvoidingView>
The code for the <UserId/> component, which we want to support scrolling for this time.
<View>
<View style={styles.searchBoxStyle}>
<View style={styles.searchWrapperStyle}>
<Pressable style={styles.searchContainerStyle} onPress={() => textInputUserId.focus()}>
<Text style={styles.searchTitleStyle}>UserId</Text>
{/* <KeyboardAvoidingView behavior="padding"> */}
<View style={defaultUserIdBorderColor ? isCorrectUserIdSymbol && isCorrectUserIdStringCount ? styles.searchViewStyle : [styles.searchViewStyle, styles.inputIncorrectBorderColorStyle]: styles.searchViewStyle}>
<Image source={require("../../../assets/profile.png")} style={styles.searchIconStyle}/>
{/* <KeyboardAvoidingView behavior="padding"> */}
<TextInput
onChangeText={onChangeUserIdText}
style={styles.searchContentStyle}
value={userIdText}
placeholder="test1234"
inputAccessoryViewID={inputAccessoryViewID}
ref={(input) => textInputUserId = input}
autoCapitalize="none"
maxLength={100}
textContentType="username"
onFocus={() => {
…
}}
onEndEditing={() => {
…
}}
/>
</View>
</Pressable>
</View>
</View>
{/* UserId Description */}
{displayUserIdDescription ? !isCorrectUserIdSymbol || !isCorrectUserIdStringCount || !isAvailableUserId ? (
<View style={styles.descriptionBoxStyle}>
<View style={styles.descriptionWrapperStyle}>
<View style={styles.descriptionContainerStyle}>
{!defaultDisplayUserIcons ? isCorrectUserIdSymbol ? <Image source={require("../../../assets/correct.png")} style={styles.descriptionIconStyle}/>: <Image source={require("../../../assets/incorrect.png")} style={styles.descriptionIconStyle}/>: null}
<Text style={styles.descriptionTextStyle}>Half-width alphanumeric characters only.</Text>
</View>
<View style={styles.descriptionContainerStyle}>
{!defaultDisplayUserIcons ? isCorrectUserIdStringCount ? <Image source={require("../../../assets/correct.png")} style={styles.descriptionIconStyle}/>: <Image source={require("../../../assets/incorrect.png")} style={styles.descriptionIconStyle}/>: null}
<Text style={styles.descriptionTextStyle} >More than 4 words and less than 100 words.</Text>
</View>
<View style={styles.descriptionContainerStyle}>
{!defaultDisplayUserIcons ? isAvailableUserId ? <Image source={require("../../../assets/correct.png")} style={styles.descriptionIconStyle}/>: <Image source={require("../../../assets/incorrect.png")} style={styles.descriptionIconStyle}/>: null}
<Text style={styles.descriptionTextStyle} >Available.</Text>
</View>
</View>
</View>
) : null: null}
</View>
Style sheet code.
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
containerStyle: {
flex: 1,
backgroundColor: "#1B1C56",
},
headContainerStyle: {
width: "100%",
height: "10%",
height: 40,
backgroundColor: "#1B1C56",
},
headMessageContainerStyle: {
backgroundColor: "#feffff",
alignItems: 'center',
},
headMessageTextStyle: {
fontSize: 50,
fontFamily: "AlfaSlabOne_400Regular",
color: "#1B1C56",
marginBottom: 32,
},
mainContainerStyle: {
width: "100%",
height: "15%",
backgroundColor: "#feffff",
borderTopLeftRadius: 50,
alignItems: 'center',
},
searchBoxStyle: {
flex: 1,
backgroundColor: "#feffff",
},
searchWrapperStyle: {
flex: 1,
alignItems: "center",
paddingBottom: 10,
},
searchContainerStyle: {
},
searchTitleStyle: {
fontFamily: "ABeeZee_400Regular_Italic",
color: "#262626",
marginBottom: 5,
},
searchIconStyle: {
width: 24,
height: 24,
marginRight: 10,
marginLeft: 10,
},
searchViewStyle: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#F6F7FB',
borderWidth: 0.5,
height: 60,
borderRadius: 5,
width: 300,
borderColor: "#F6F7FB",
},
searchContentStyle: {
flex: 1
},
inputIncorrectBorderColorStyle:{
borderWidth: 2,
borderColor: "#ED195E",
},
completeBoxStyle: {
width: 60,
alignItems: "center",
padding: 10,
},
completeTextStyle: {
fontSize: 18,
fontWeight: "bold",
color: "hsl(210, 100%, 60%)"
},
passwordIconStyle: {
marginRight: 10
},
descriptionBoxStyle:{
display: "flex",
alignItems: "center",
backgroundColor: "#feffff",
paddingBottom: 10,
},
descriptionWrapperStyle: {
},
descriptionContainerStyle: {
flexDirection: "row",
width: 300,
},
descriptionTextStyle: {
color: "#262626",
fontSize: 12,
overflow: "visible"
},
descriptionIconStyle:{
marginRight: 10,
width: 12,
height: 12,
},
bottomStyle: {
display: "flex",
alignItems: "center",
height: "100%",
backgroundColor: "#feffff",
},
buttonContainerStyle: {
alignItems: "center",
justifyContent: "center",
backgroundColor: "#1B1C56",
width: 300,
height: 60,
borderRadius: 10,
fontSize: 18,
},
buttonContainerInvalidStyle:{
backgroundColor: "#C5C5C7",
},
buttonTextStyle: {
color: "#feffff",
fontFamily: "ABeeZee_400Regular_Italic",
},
toLoginStyle: {
marginTop: 10,
height: "5%",
flexDirection: "row"
},
toLoginTextStyle: {
fontFamily: "ABeeZee_400Regular_Italic",
},
toLoginTextLinkStyle: {
color: "#ED195E",
marginLeft: 10,
},
});
Swapped the positions of KeyboardAvoidingView, SafeAreaView and ScrollView. I have tried to set the keyboardVerticalOffset and the keyboardVerticalOffset, but each had its own problems, and the current code was the closest to the ideal.
I found this great code sample/layout -- see below -- for a React Native login screen. All I want to do is to have an ImageBackground as opposed to the current solid background.
When I add ImageBackground to the code, it throws everything off and instead of the image covering the entire screen, everything gets squished in the middle and all alingment gets out of whack. What am I doing wrong here?
Here's the original code with solid background:
import React from 'react';
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';
export default class App extends React.Component {
state={
email:"",
password:""
}
render(){
return (
<View style={styles.container}>
<Text style={styles.logo}>HeyAPP</Text>
<View style={styles.inputView} >
<TextInput
style={styles.inputText}
placeholder="Email..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({email:text})}/>
</View>
<View style={styles.inputView} >
<TextInput
secureTextEntry
style={styles.inputText}
placeholder="Password..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({password:text})}/>
</View>
<TouchableOpacity>
<Text style={styles.forgot}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>LOGIN</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.loginText}>Signup</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#003f5c',
alignItems: 'center',
justifyContent: 'center',
},
logo:{
fontWeight:"bold",
fontSize:50,
color:"#fb5b5a",
marginBottom:40
},
inputView:{
width:"80%",
backgroundColor:"#465881",
borderRadius:25,
height:50,
marginBottom:20,
justifyContent:"center",
padding:20
},
inputText:{
height:50,
color:"white"
},
forgot:{
color:"white",
fontSize:11
},
loginBtn:{
width:"80%",
backgroundColor:"#fb5b5a",
borderRadius:25,
height:50,
alignItems:"center",
justifyContent:"center",
marginTop:40,
marginBottom:10
},
loginText:{
color:"white"
}
});
This produces this nice layout:
And I simply add an image background with the following code which doesn't work at all:
<View style={styles.container}>
<ImageBackground
source={require("../../assets/images/background/teton_snake_dimmed.jpg")}
style={styles.imageBackground}
>
<Text style={styles.logo}>HeyAPP</Text>
<View style={styles.inputView} >
<TextInput
style={styles.inputText}
placeholder="Email..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({ email: text })} />
</View>
<View style={styles.inputView}>
<TextInput
secureTextEntry
style={styles.inputText}
placeholder="Password..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({ password: text })} />
</View>
<TouchableOpacity>
<Text style={styles.forgot}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>LOGIN</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.loginText}>Signup</Text>
</TouchableOpacity>
</ImageBackground>
</View>
And here's the updated styles. The only thing I add is the imageBackground:
container: {
flex: 1,
backgroundColor: '#003f5c',
alignItems: 'center',
justifyContent: 'center',
},
logo: {
fontWeight: "bold",
fontSize: 50,
color: "#fb5b5a",
marginBottom: 40
},
imageBackground: {
flex: 1,
resizeMode: "cover"
},
inputView: {
width: "80%",
backgroundColor: "#465881",
borderRadius: 25,
height: 50,
marginBottom: 20,
justifyContent: "center",
padding: 20
},
inputText: {
backgroundColor: "#465881",
height: 50,
color: "white"
},
forgot: {
color: "white",
fontSize: 11
},
loginBtn: {
width: "80%",
backgroundColor: "#fb5b5a",
borderRadius: 25,
height: 50,
alignItems: "center",
justifyContent: "center",
marginTop: 40,
marginBottom: 10
},
loginText: {
color: "white"
}
});
What am I doing wrong here?
P.S. Here's the original code published by #Alhydra:
https://github.com/Alhydra/React-Native-Login-Screen-Tutorial/blob/master/App.js
Here is an example replace the image with the image you want
snack: https://snack.expo.io/#ashwith00/intelligent-banana
code:
import React from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
Image,
} from 'react-native';
export default class App extends React.Component {
state = {
email: '',
password: '',
};
render() {
return (
<View style={styles.container}>
<Image
style={styles.image}
source={{
uri:
'https://media.gettyimages.com/videos/loopable-color-gradient-background-animation-video-id1182636595?s=640x640',
}}
/>
<View style={styles.subContainer}>
<Text style={styles.logo}>HeyAPP</Text>
<View style={styles.inputView}>
<TextInput
style={styles.inputText}
placeholder="Email..."
placeholderTextColor="#003f5c"
onChangeText={(text) => this.setState({ email: text })}
/>
</View>
<View style={styles.inputView}>
<TextInput
secureTextEntry
style={styles.inputText}
placeholder="Password..."
placeholderTextColor="#003f5c"
onChangeText={(text) => this.setState({ password: text })}
/>
</View>
<TouchableOpacity>
<Text style={styles.forgot}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>LOGIN</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.loginText}>Signup</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
image: {
flex: 1,
},
container: {
flex: 1,
backgroundColor: '#003f5c',
},
subContainer: {
...StyleSheet.absoluteFillObject,
alignItems: 'center',
justifyContent: 'center',
},
logo: {
fontWeight: 'bold',
fontSize: 50,
color: '#fb5b5a',
marginBottom: 40,
},
inputView: {
width: '80%',
backgroundColor: '#465881',
borderRadius: 25,
height: 50,
marginBottom: 20,
justifyContent: 'center',
padding: 20,
},
inputText: {
height: 50,
color: 'white',
},
forgot: {
color: 'white',
fontSize: 11,
},
loginBtn: {
width: '80%',
backgroundColor: '#fb5b5a',
borderRadius: 25,
height: 50,
alignItems: 'center',
justifyContent: 'center',
marginTop: 40,
marginBottom: 10,
},
loginText: {
color: 'white',
},
});
Hello I am fairly new to React Native and am currently having an issue with my modal component. My modal component has two props, gameData and isModalVisible. In Home.js modal prop isModalVisible has the value of a state variable isVisible that gets changed to true when a certain TouchableOpacity is pressed. Then inside my FeaturedGameModal.js isModalVisible is set from props. The issue I am having is closing the modal. Opening the modal this way works fine, but how should I close the modal since its visibility is being controlled by props that are in Home.js? Any help would be greatly appreciated. I have been working on this for two days now and it is driving me crazy. Thanks! I will include my two files in case you want to more closely inspect my code.
Home.js:
import React from 'react';
import {
View,
Text,
Image,
SafeAreaView,
TouchableOpacity,
ActivityIndicator,
Linking,
ScrollView,
TouchableHighlight,
} from 'react-native';
import {homeStyles} from '../styles/homeStyles';
import {styles} from '../styles/styles';
import {createIconSetFromIcoMoon} from 'react-native-vector-icons';
import icoMoonConfig from '../../assets/fonts/selection.json';
import {fetchData} from '../functions/fetch';
import Modalz from '../modals/FeaturedGameModal';
const Icon = createIconSetFromIcoMoon(icoMoonConfig);
class Home extends React.Component {
myData = {};
constructor(props) {
super(props);
this.state = {
error: false,
isFetching: true,
featuredGameModal: false,
isVisible: false,
};
}
handleFeaturedGame = async () => {
this.setState({}, async () => {
try {
const featureGameData = await fetchData(
'http://dev.liberty.edu/templates/flames/json/json_appHomeFeed.cfm',
);
this.setState({
error: false,
featuredGameData: featureGameData,
isFetching: false,
});
} catch (e) {
this.setState({
error: true,
});
console.log(e.message);
}
});
};
handleFeaturedModal() {
this.setState({featuredGameModal: false});
}
componentDidMount() {
this.handleFeaturedGame();
}
render() {
const {featuredGameData} = this.state;
return this.state.isFetching ? (
<View style={styles.center}>
<ActivityIndicator size="large" color="#AE0023" />
</View>
) : (
<ScrollView>
<SafeAreaView>
<View style={homeStyles.featuredGameContainer}>
<View style={homeStyles.centerHor}>
<Image
style={homeStyles.logo}
source={require('../../assets/images/FlamesLogo.png')}
/>
</View>
<View style={homeStyles.gameTimeContainer}>
<Text style={homeStyles.gameTime}>
{featuredGameData.featuredGame.eventdate}
</Text>
<Text style={homeStyles.gameTime}>
{featuredGameData.featuredGame.eventtime}
</Text>
</View>
<TouchableOpacity
activeOpacity={0.6}
onPress={() => {
this.setState({isVisible: true});
}}>
<View style={homeStyles.contentContainer}>
<View style={homeStyles.contentLeft}>
<Text style={homeStyles.teamText}>
{featuredGameData.featuredGame.teamname}
</Text>
<Text style={homeStyles.opponentText}>
vs {featuredGameData.featuredGame.opponent}
</Text>
<Text style={homeStyles.locationText}>
<Icon size={12} name={'location'} />
{featuredGameData.featuredGame.location}
</Text>
</View>
<View style={homeStyles.contentRight}>
<Image
style={homeStyles.opponentLogo}
source={{
uri: featuredGameData.featuredGame.OpponentLogoFilename,
}}
/>
</View>
</View>
</TouchableOpacity>
<View style={homeStyles.allContent}>
<Modalz
gameData={this.state.featuredGameData.featuredGame}
isModalVisible={this.state.isVisible}
/>
<View style={homeStyles.contentContainerBottom}>
<View style={homeStyles.contentLeft}>
<TouchableOpacity
style={homeStyles.buyTicketBtn}
onPress={() =>
Linking.openURL(featuredGameData.featuredGame.buyTickets)
}>
<Text style={homeStyles.buyTicketBtnText}>Buy Tickets</Text>
</TouchableOpacity>
</View>
<View style={homeStyles.liveContainer}>
<Text style={homeStyles.live}>Experience Live:</Text>
<View style={homeStyles.liveIconsContainer}>
<Icon
style={{color: '#FFF', marginRight: 4}}
size={15}
name={'radio'}
/>
<Icon style={{color: '#FFF'}} size={12} name={'LFSN'} />
</View>
</View>
</View>
</View>
</View>
<View style={homeStyles.newsContainer}>
{featuredGameData.News.map((item, key) => (
<View
key={key}
style={[homeStyles.centerHor, homeStyles.newsCard]}>
<Image
style={homeStyles.newsImage}
source={{
uri: item.Thumbnail,
}}
/>
<Text style={homeStyles.headline}>{item.Headline}</Text>
<View style={homeStyles.teamNameView}>
<Text style={homeStyles.teamNameText}>{item.teamname}</Text>
<Text>{item.GameDate}</Text>
</View>
</View>
))}
</View>
</SafeAreaView>
</ScrollView>
);
}
}
export default Home;
FeaturedGameModal.js:
import React from 'react';
import {
Alert,
Modal,
StyleSheet,
Text,
TouchableHighlight,
View,
Image,
Dimensions,
TouchableOpacity,
SafeAreaView,
} from 'react-native';
import {createIconSetFromIcoMoon} from 'react-native-vector-icons';
import icoMoonConfig from '../../assets/fonts/selection';
import {homeStyles} from '../styles/homeStyles';
const Icon = createIconSetFromIcoMoon(icoMoonConfig);
const windowWidth = Dimensions.get('window').width;
export default class Modalz extends React.Component {
constructor(props) {
super(props);
this.state = {
teamName: props.gameData.teamname,
opponentName: props.gameData.opponent,
eventDate: props.gameData.eventdate,
liveAudioURL: props.gameData.LiveAudioURL,
liveStatsURL: props.gameData.LiveStatsURL,
videoURL: props.gameData.VideoURL,
opponentLogoURL: props.gameData.OpponentLogoFilename,
};
}
render() {
const {
opponentName,
teamName,
eventDate,
opponentLogoURL,
liveStatsURL,
liveAudioURL,
videoURL,
location,
} = this.state;
const {isModalVisible} = this.props;
return (
<View>
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={isModalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<SafeAreaView style={{flex: 1, backgroundColor: 'transparent'}}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Icon
style={styles.closeButton}
size={25}
name={'x'}
onPress={() => {}}
/>
<Text style={styles.upcomingGameTitle}>
{teamName} vs {opponentName}
</Text>
<Text style={styles.upcomingGameSubtitle}>{eventDate}</Text>
<View style={styles.facingLogosBlock}>
<View style={styles.leftTeamBlock} />
<View style={styles.rightTeamBlock} />
<View style={styles.vsTextWrapper}>
<Text style={styles.vsText}>VS</Text>
</View>
<View style={styles.logoWrapper}>
<Image
style={styles.facingLogoImg}
source={{
uri:
'https://www.liberty.edu/templates/flames/images/flamesMonogram.png',
}}
/>
<Image
style={styles.facingLogoImg}
source={{uri: opponentLogoURL}}
/>
</View>
</View>
<View>
<TouchableOpacity style={styles.buyTicketBtn}>
<Text style={styles.buyTicketBtnText}>Buy Tickets</Text>
</TouchableOpacity>
</View>
<View style={styles.buttonRow}>
<TouchableOpacity
style={{...styles.iconButton, ...styles.iconButtonLeft}}>
<Icon
style={styles.iconButtonIcon}
size={25}
name={'flag'}
onPress={() => {
this.toggleModal(!this.state.modalVisible);
}}
/>
<Text style={styles.iconButtonText}>Game Day</Text>
</TouchableOpacity>
<TouchableOpacity
style={{...styles.iconButton, ...styles.iconButtonRight}}>
<Icon
style={styles.iconButtonIcon}
size={25}
name={'stats'}
onPress={() => {
this.toggleModal(!this.state.modalVisible);
}}
/>
<Text style={styles.iconButtonText}>Live Stats</Text>
</TouchableOpacity>
</View>
<View style={styles.liveLinkBlock}>
<View style={styles.liveLinkLeft}>
<Icon
style={styles.iconButtonIcon}
size={18}
name={'LFSN'}
/>
<Text>The Journey 88.3 FM</Text>
</View>
<TouchableOpacity style={styles.liveButton}>
<Text style={styles.liveButtonText}>Listen Live</Text>
</TouchableOpacity>
</View>
<View style={styles.liveLinkBlock}>
<View style={styles.liveLinkLeft}>
<Icon
style={styles.iconButtonIcon}
size={18}
name={'espn3'}
/>
<Text>LFSN TV Production</Text>
</View>
<TouchableOpacity style={styles.liveButton}>
<Text style={styles.liveButtonText}>Watch Live</Text>
</TouchableOpacity>
</View>
</View>
</View>
</SafeAreaView>
</Modal>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
modalView: {
flex: 1,
alignSelf: 'stretch',
backgroundColor: 'white',
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
paddingTop: 14,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
openButton: {
backgroundColor: '#F194FF',
borderRadius: 20,
padding: 10,
elevation: 2,
},
closeButton: {
position: 'absolute',
right: 16,
top: 16,
color: '#000',
},
closeText: {
color: '#000',
fontWeight: 'bold',
textAlign: 'center',
fontSize: 20,
},
upcomingGameTitle: {
color: '#19191A',
fontSize: 18,
fontWeight: 'bold',
},
upcomingGameSubtitle: {
color: '#747676',
fontSize: 13,
fontWeight: 'bold',
marginBottom: 16,
},
modalText: {
marginBottom: 15,
textAlign: 'center',
},
facingLogosBlock: {
flexDirection: 'row',
position: 'relative',
alignItems: 'center',
},
facingLogoImg: {
width: 100,
height: 100,
resizeMode: 'contain',
flex: 1,
},
leftTeamBlock: {
width: 0,
height: 0,
backgroundColor: 'transparent',
borderStyle: 'solid',
borderRightWidth: 35,
borderTopWidth: 185,
borderRightColor: 'transparent',
borderTopColor: '#AE0023',
borderLeftColor: '#AE0023',
borderLeftWidth: windowWidth / 2,
left: 15,
zIndex: -1,
position: 'relative',
},
rightTeamBlock: {
width: 0,
height: 0,
backgroundColor: 'transparent',
borderStyle: 'solid',
borderLeftWidth: 35,
borderBottomWidth: 185,
borderBottomColor: '#461964',
borderRightColor: '#461964',
borderLeftColor: 'transparent',
borderRightWidth: windowWidth / 2,
right: 15,
zIndex: -1,
position: 'relative',
},
vsTextWrapper: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center',
},
vsText: {
color: '#000000',
backgroundColor: '#FFFFFF',
padding: 5,
fontWeight: 'bold',
},
logoWrapper: {
position: 'absolute',
width: windowWidth,
height: 185,
top: 0,
left: 35,
flexDirection: 'row',
alignItems: 'center',
},
buyTicketBtn: {
marginTop: 24,
backgroundColor: '#AE0023',
borderRadius: 4,
paddingVertical: 20,
paddingHorizontal: 12,
width: windowWidth - 24,
},
buyTicketBtnText: {
fontSize: 21,
color: '#fff',
fontWeight: 'bold',
alignSelf: 'center',
textTransform: 'uppercase',
},
buttonRow: {
paddingVertical: 24,
paddingHorizontal: 12,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
iconButton: {
backgroundColor: '#F0F3F5',
borderRadius: 4,
paddingVertical: 14,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
flex: 1,
},
iconButtonText: {
color: '#19191A',
fontWeight: 'bold',
fontSize: 16,
marginLeft: 10,
},
iconButtonIcon: {
color: '#000',
},
iconButtonLeft: {
marginRight: 6,
},
iconButtonRight: {
marginLeft: 6,
},
liveLinkBlock: {
padding: 12,
borderStyle: 'solid',
borderTopColor: '#F0F3F5',
borderTopWidth: 1,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
},
liveButton: {
backgroundColor: '#F0F3F5',
borderRadius: 4,
paddingVertical: 14,
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
liveButtonText: {
color: '#19191A',
fontWeight: 'bold',
fontSize: 16,
},
liveLinkLeft: {
flex: 2,
},
});
You should create hideModal function in Home.js then pass it to Modalz component.
In Home.js, add this function:
hideModalz = () => {
this.setState({isVisible: true});
}
And pass this function to Modalz props:
<Modalz
gameData={this.state.featuredGameData.featuredGame}
isModalVisible={this.state.isVisible}
hide={hideModalz}
/>
In Modalz, call this.props.hide(); if you want to hide modal.
I used the other question to fix it my problem but I don't understand where I mistake.
Hi,
I have a problem with react native scroll view, it scroll but when I release it comes back to the top, how can I fix it?
This is the render:
render() {
const { centerEverything, skeleton, container, textContainer, contentContainer, buttonContainer,
propHeight, propWidth, halfPropWidth, titleContainer, descContainer, title, artworkTitle,
desc, buttonStyle, artworkContainer, artwork } = styles;
let CheckIndex = i => {
if((i % 2) == 0) {
return styles.gray
}
};
let rows = this.state.rows.map((r, i) => {
return <View key={ i } style={{ flexDirection: 'row' }}>
<Input
propWidth={halfPropWidth}
placeholder="Ingrediente"
onChangeText={this.changeIngrediente.bind(this, 'quantita', i)}
value={this.state.date} />
<Input
propWidth={halfPropWidth}
placeholder="Quantita"
onChangeText={this.changeIngrediente.bind(this, 'ingrediente', i)}
value={this.state.time} />
</View>
});
return (
<TouchableWithoutFeedback onPress={()=> dismissKeyboard()}>
<View style={[centerEverything, container]}>
<View style={[centerEverything, textContainer]}>
<View style={titleContainer}>
<Text style={[title]}>Add Event</Text>
</View>
<View style={descContainer}>
<Text style={[desc]}>Submit your event and we will process it in a bit ⚡️</Text>
</View>
</View>
<ScrollView style={[contentContainer, propWidth]}>
<View style={[centerEverything, artworkContainer]}>
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
<View style={[centerEverything, {height: 100, width: deviceWidth*0.8}]}>
{
(() => {
switch (this.state.artworkUrl) {
case null:
return (
<View>
<Text style={[artworkTitle]}>Upload event artwork</Text>
<Text style={[desc]}>Preferably 640x480</Text>
</View>
);
case '':
return <Spinner size="small"/>
default:
return(
<Image style={artwork} source={{uri: this.state.artworkUrl}} />
)
}
})()
}
</View>
</TouchableOpacity>
</View>
<Input
propWidth={propWidth}
placeholder="Event Title"
onChangeText={(title) => this.setState({ title })}
value={this.state.title} />
<View style={{ flexDirection: 'row' }}>
<Input
propWidth={halfPropWidth}
placeholder="Date"
onChangeText={(date) => this.setState({ date })}
value={this.state.date} />
<Input
propWidth={halfPropWidth}
placeholder="Time"
onChangeText={(time) => this.setState({ time })}
value={this.state.time} />
</View>
<View>
{ rows }
<TouchableHighlight
onPress={ this._addRow.bind(this) }
style={styles.button}>
<Text>Aggiungi ingrediente</Text>
</TouchableHighlight>
</View>
<View style={{ flexDirection: 'row' }}>
<Input
propWidth={halfPropWidth}
placeholder="Organizer"
onChangeText={(organizer) => this.setState({ organizer })}
value={this.state.organizer} />
<Input
propWidth={halfPropWidth}
placeholder="Cost"
onChangeText={(cost) => this.setState({ cost })}
value={this.state.cost} />
</View>
<Input
propWidth={[propHeight, propWidth]}
placeholder="Address"
multiline={true}
onChangeText={(address) => this.setState({ address })}
value={this.state.address} />
<Input
propWidth={[propHeight, propWidth]}
placeholder="Note"
multiline={true}
onChangeText={(note) => this.setState({ note })}
value={this.state.note} />
</ScrollView>
<View style={[buttonContainer]}>
<ButtonComponent
style={buttonStyle}
type='primary'
shape='rectangle'
buttonState={this.state.buttonState}
states={this.buttonStates}
/>
</View>
</View>
</TouchableWithoutFeedback>
)
}
this is the style:
const styles = {
centerEverything: {
justifyContent: 'center',
alignItems: 'center'
},
skeleton: {
borderWidth: 1,
borderColor: 'red'
},
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#F5F6F7',
marginTop: 44
},
textContainer: {
flex: 2,
marginTop: 20
},
propHeight: {
height: 80
},
propWidth: {
width: deviceWidth*0.8
},
halfPropWidth: {
width: deviceWidth*0.4
},
contentContainer: {
flex: 1,
width: deviceWidth,
height: deviceHeight-200
},
buttonContainer: {
width: deviceWidth,
alignItems: 'center',
backgroundColor: 'transparent',
position: 'absolute',
bottom: 20
},
button: {
alignItems: 'center',
justifyContent: 'center',
height:55,
backgroundColor: '#ededed',
marginBottom:10
},
titleContainer: {
width: deviceWidth*0.8,
},
descContainer: {
width: deviceWidth*0.6,
},
title: {
fontSize: 22,
fontFamily: 'Helvetica Neue',
fontWeight: '400',
textAlign: 'center'
},
artworkTitle: {
fontSize: 18
},
desc: {
color: 'grey',
fontSize: 15,
fontFamily: 'Helvetica Neue',
fontWeight: '300',
textAlign: 'center'
},
buttonStyle: {
height: 40,
width: deviceWidth*0.7,
borderRadius: 20,
margin: 3
},
artworkContainer: {
borderColor: '#9B9B9B',
borderRadius: 3,
borderWidth: 1 / PixelRatio.get(),
marginBottom: 5,
width: deviceWidth*0.8,
height: 100
},
artwork: {
width: deviceWidth*0.8,
height: 100
},
listViewContainer: {
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
flexWrap: 'wrap',
},
}
I set minheight property of the scroll and it seems to work.