multiline header - React Native - javascript

I have a React Native App.
I want to add a subtitle below my header.
Something like this
Header Code:
static navigationOptions = ({ navigation }) => {
return {
title: localizedTitle(),
headerTintColor: '#fff',
headerStyle: {
backgroundColor: isUndercareMode() ? getUndercareColor() : 'rgb(255,0,0)'
},
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
fontSize: normalizeFontSize(18),
flex: 1
},
headerLeft: <BackButton
accessible={false}
testID='LeftButton'
accessibilityLabel="headerLeftButton"
/>,
headerRight: (<View></View>),
}
}
How can I implement this multiline header?
Update:
I tried 2 ways and both are so frustrating.
1st method:
the back button and user details are not aligned. the back button is moved up.
static navigationOptions = ({ navigation }) => {
return {
title: localizedTitle(),
headerTintColor: '#fff',
headerStyle: {
backgroundColor: HAGo_isUndercareMode() ? HAGo_getUndercareColor() : 'rgb(255,0,0)'
},
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
fontSize: normalizeFontSize(18),
flex: 1
},
headerLeft: (
<View>
<HAGo_BackButton
accessible={false}
testID='LeftButton'
accessibilityLabel="headerLeftButton"
/>
{
HAGo_isUndercareMode() ?
<View >
<View style={{flexDirection: 'row', backgroundColor:'#008A20', width:500, alignItems:'center'}}>
<Image style={{ width:40, height:40, marginRight:15}} source={require('../HAGo/default_userIcon.png')} />
<Text style={{fontSize: normalizeFontSize(18), color:'#fff'}}>{getUndercareName()}</Text>
</View>
</View>
: null
}
</View>
),
headerRight: (<View></View>),
}
}
2nd method:
not able to align them to the left.
static navigationOptions = ({ navigation }) => {
return {
headerTitle: () =>
<View>
<Text style={{color: '#fff', fontSize:normalizeFontSize(18), fontWeight:'bold'}} >{localizedTitle()}</Text>
<View style={{flexDirection: 'row', justifyContent: 'flex-start'}}>
<Image style={{ width:40, height:40, marginRight:15}} source={require('../HAGo/default_userIcon.png')} />
<Text style={{fontSize: normalizeFontSize(18), color:'#fff'}}>{getUndercareName()}</Text>
</View>
</View>,
headerTintColor: '#fff',
headerStyle: {
backgroundColor: HAGo_isUndercareMode() ? HAGo_getUndercareColor() : 'rgb(255,0,0)'
},
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
fontSize: normalizeFontSize(18),
flex: 1
},
headerLeft: <HAGo_BackButton
accessible={false}
testID='LeftButton'
accessibilityLabel="headerLeftButton"
/>,
headerRight: (<View></View>),
}
}
Which method makes sense?? Please help.
2nd Update:
static navigationOptions = ({ navigation }) => {
return {
title: localizedTitle(),
headerTintColor: '#fff',
headerStyle: {
backgroundColor: isUndercareMode() ? getUndercareColor() : 'rgb(255,0,0)'
},
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
fontSize: normalizeFontSize(18),
flex: 1
},
headerLeft: (
<View>
<View style={{paddingTop: isUndercareMode() ? 45 : 0}} >
<BackButton
accessible={false}
testID='LeftButton'
accessibilityLabel="headerLeftButton"
/>
</View>
{
isUndercareMode() ?
<Undercare />
: null
}
</View>
),
headerRight: (<View></View>),
}
}
Undercare component:
export default class Undercare extends React.Component {
render() {
return (
<View>
<View style={{flexDirection: 'row', width:500, height:58, alignItems:'center', paddingLeft:25, backgroundColor:'#008A20', paddingTop:15, paddingBottom:20, backgroundColor:'#008A20'}}>
<Image style={{ width:50, height:50, marginRight:20}} source={require('../HAGo/default_userIcon.png')} />
<Text style={{fontSize: normalizeFontSize(18), color:'#fff'}}>{getUndercareName()}</Text>
</View>
</View>
)
}
}
The back button is not correctly aligned with Notification centre title :/

You can create a custom header component and pass that as an option in order to overwrite the default header.
See this snack for a working example: https://snack.expo.io/#zayco/header-styles_custom
Replace all of the old header options with header
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
header: () => renderHeader()
}}
/>
</Stack.Navigator>
</NavigationContainer>
Add the function to render the custom header
const renderHeader = () => (
<View style={styles.header}>
<View style={styles.headerTop}>
<View style={styles.headerLeft}>
<Text>Back</Text>
</View>
<View style={styles.headerCenter}>
<Text style={styles.headerTitle}>Notification Center</Text>
</View>
<View style={styles.headerRight} />
</View>
<View style={styles.subHeader}>
<View style={styles.subHeaderLeft}>
<Text>ICON</Text>
</View>
<View style={styles.subHeaderCenter}>
<Text style={styles.subHeaderName}>CHUI, Tai Hung</Text>
</View>
</View>
</View>
)
Add the styles used by the custom header. You can play around with the styles to fit your needs.
const styles = {
header: {
flex: 0,
backgroundColor: 'green',
marginTop: Platform.OS == "ios" ? 20 : 0, // only for IOS to give StatusBar Space
padding: 10,
},
headerTop: {
flexDirection: 'row',
},
headerLeft: {
flex: 1,
backgroundColor: 'red',
justifyContent: 'center',
},
headerCenter: {
flex: 6,
alignItems: 'center',
},
headerTitle: {
fontSize: 18,
color: 'white',
fontWeight: 'bold',
},
headerRight: {
flex: 1,
},
subHeader: {
flexDirection: 'row',
paddingTop: 10,
},
subHeaderLeft: {
backgroundColor: 'yellow',
padding: 5,
},
subHeaderCenter: {
justifyContent: 'center',
alignItems: 'center',
},
subHeaderName: {
color: 'white',
marginLeft: 10,
}
}

instead of using title use headerTitle in which you can add a component instead of a string.
static navigationOptions = ({ navigation }) => {
return {
headerTitle: () =>
<View>
<Text>{localizedTitle()}</Text>
<Text>subtitle</Text>
</View>,
headerTintColor: '#fff',
headerStyle: {
backgroundColor: isUndercareMode() ? getUndercareColor() : 'rgb(255,0,0)'
},
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
fontSize: normalizeFontSize(18),
flex: 1
},
headerLeft: <BackButton
accessible={false}
testID='LeftButton'
accessibilityLabel="headerLeftButton"
/>,
headerRight: (<View></View>),
}
}

Related

Is there any other way I can call the verify function to makeWithdraw

Good day guys, I've been stuck with react native, I have a withdrawal screen that navigates to transactionPin screen, I have a not so wonderful custom onScreen keyboard, that only accepts maximum of 4 input. I am checking if length equals 4, the verify function will trigger and perform any of the transfer or makeWithdraw, but it results in Maximum depth... looping, how do I rewrite this, please. Below is my code. I appreciate any help greatly.
withdrawScreen.js
import React, { Component } from "react";
import { Text, View, StyleSheet, SafeAreaView, StatusBar, Image, TouchableOpacity, ScrollView, TextInput, ActivityIndicator } from "react-native";
import { withNavigation } from "react-navigation";
import * as Yup from 'yup';
import { Colors, Sizes } from "../../constant/styles";
import { MaterialIcons, MaterialCommunityIcons, Feather } from '#expo/vector-icons';
import Swipeable from 'react-native-gesture-handler/Swipeable';
import AppForm from "../../component/appForm";
import AppFormField from "../../component/appFormField";
import AppButton from "../../component/appButton";
import dashApi from "../../api/dashApi";
import Loader from "../../component/Loader";
import TransactionPinScreen from "./transactionPinScreen";
const validationSchema = Yup.object().shape({
withdrawal_method: Yup.object().required('Select withdrawal method'),
authorization_mode: Yup.object().required('Select verification type')
});
const initialState = {
initialState: 0,
text: '',
withdrawalMethod: [{ label: 'Select withdrawal method', value: '-', disabled: true }],
authorizationMode: [{ label: 'Select authorization mode', value: '-', disabled: true }],
initialLoading: false,
withdrawMethodDesc: '',
verification: '',
withdrawalWindow: {},
}
class WithdrawScreen extends Component {
componentDidMount() {
this.getWithdrawalData();
}
componentWillUnmount() {
this.setState(initialState);
}
constructor(props) {
super(props);
this.state = initialState;
// this.makeWithdraw = this.makeWithdraw.bind(this);
};
getWithdrawalData = async () => {
this.setState({ initialLoading: true });
const result = await dashApi.withdrawalData();
if (result.status == 200) {
let withdrawalMethod = [];
let authorizationMode = [];
result.data.withdrawal_method.map(e => withdrawalMethod.push({ label: e.name, value: e.name, ...e }));
result.data.authorization_mode.map(e => authorizationMode.push({ label: e.text, ...e }));
this.setState({ initialLoading: false });
this.setState({ withdrawalMethod: [...this.state.withdrawalMethod, ...withdrawalMethod] });
this.setState({ authorizationMode: [...this.state.authorizationMode, ...authorizationMode] });
this.setState({ withdrawalWindow: result.data.withdrawal_window })
}
else if (result.status == 401) {
this.setState({ errorText: result.data.message });
this.setState({ initialLoading: false });
}
else {
this.setState({ initialLoading: false });
this.setState({ errorText: 'Network Error' })
}
};
onPress1 = () => {
this.setState({ text: this.state.text + '1' })
}
onPress2 = () => {
this.setState({ text: this.state.text + '2' })
}
onPress3 = () => {
this.setState({ text: this.state.text + '3' })
}
onPress4 = () => {
this.setState({ text: this.state.text + '4' })
}
onPress5 = () => {
this.setState({ text: this.state.text + '5' })
}
onPress6 = () => {
this.setState({ text: this.state.text + '6' })
}
onPress7 = () => {
this.setState({ text: this.state.text + '7' })
}
onPress8 = () => {
this.setState({ text: this.state.text + '8' })
}
onPress9 = () => {
this.setState({ text: this.state.text + '9' })
}
onPress0 = () => {
this.setState({ text: this.state.text + '0' })
}
onPressDecimal = () => {
this.setState({ text: this.state.text + '.' })
}
onPressBackspace = () => {
let text = this.state.text.slice(0, this.state.text.length - 1);
this.setState({ text: text })
}
render() {
return (
<SafeAreaView style={styles.screenContainer}>
<StatusBar backgroundColor={Colors.backgroundColor} barStyle="dark-content" />
<View>
{this.header()}
<ScrollView showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false} style={{ marginBottom: 50 }}>
{this.state.initialState == 0 ?
<View>
{this.withdrawalMethod()}
<Loader loading={this.state.initialLoading} />
</View>
:
<View>
{this.transferDetCard()}
{this.inputAmountLine()}
{this.buttonKeyboardMode()}
{this.swiper()}
</View>
}
</ScrollView>
</View>
</SafeAreaView>
)
}
header() {
return (
<View>
<View style={[styles.flex, { alignItems: 'center' }]}>
<TouchableOpacity style={[styles.flex, { justifyContent: 'center', alignItems: 'center' }]} onPress={() => this.props.navigation.goBack()}>
<MaterialIcons name="keyboard-arrow-left" size={35} color="black" />
<Text style={styles.textStyle}>Withdraw</Text>
</TouchableOpacity>
</View>
</View>
)
}
transferDetCard() {
return (
<View style={[styles.trnsferDetCard, styles.flex]}>
<View style={styles.flex}>
<Image source={require('../../assets/images/dashboard/avatar.jpg')} style={styles.userImage} />
<View style={{ paddingHorizontal: 15, alignSelf: 'center' }}>
<Text style={{ fontWeight: '700', fontSize: 20, lineHeight: 24 }}>Ann</Text>
<View style={[styles.flex, { alignItems: 'center' }]}>
<Feather name="credit-card" size={24} color="black" />
<View style={[styles.flex, { alignItems: 'center', paddingHorizontal: 7 }]}>
<Image source={require('../../assets/images/dashboard/ellipsisFour.png')} style={{ tintColor: 'black' }} />
<Text style={{ paddingHorizontal: 7 }}>
6301
</Text>
</View>
</View>
</View>
</View>
<View style={{ alignSelf: 'center' }}>
<MaterialIcons name="keyboard-arrow-down" size={35} color="black" />
</View>
</View>
)
}
inputAmountLine() {
return (
<View style={styles.inputAmount}>
<Text style={this.state.text != '' ? [{ left: 5 }, styles.inputIcon] : [{ left: 110 }, styles.inputIcon]}>₦</Text>
<TextInput
style={this.state.text != '' ? [styles.input, { width: '90%' }] : [{ width: '100%' }, styles.input]}
placeholder="0.00"
value={this.state.text}
underlineColorAndroid="transparent"
placeholderTextColor={'#E5E5E5'}
showSoftInputOnFocus={false}
autoFocus
caretHidden={true}
/>
</View>
)
}
buttonKeyboardMode() {
return (
<View style={{ padding: 20 }}>
<View style={[styles.flex, { marginBottom: 15 }]}>
<TouchableOpacity style={styles.keys} onPress={this.onPress1}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>1</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress2}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>2</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress3}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>3</Text>
</TouchableOpacity>
</View>
<View style={[styles.flex, { marginBottom: 15 }]}>
<TouchableOpacity style={styles.keys} onPress={this.onPress4}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>4</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress5}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>5</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress6}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>6</Text>
</TouchableOpacity>
</View>
<View style={[styles.flex, { marginBottom: 15 }]} onPress={this.onPress7}>
<TouchableOpacity style={styles.keys} onPress={this.onPress7}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>7</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress8}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>8</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress9}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>9</Text>
</TouchableOpacity>
</View>
<View style={[styles.flex, { marginBottom: 15 }]}>
<TouchableOpacity style={styles.keys} onPress={this.onPressDecimal}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>.</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress0}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>0</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPressBackspace}>
<Feather name="delete" size={24} color="black" />
</TouchableOpacity>
</View>
</View>
)
}
swiper() {
const LeftSwipeActions = () => {
return (
<View
style={{
flex: 1, backgroundColor: '#fff7da',
borderRadius: 35, justifyContent: 'center'
}}
>
</View>
);
};
const swipeFromLeftOpen = () => {
this.props.navigation.navigate('TransactionPin', { withdraw_method: this.state.withdrawMethodDesc.id, verification: this.state.verification.value, amount: this.state.text, window_status: this.state.withdrawalWindow.status, type: "withdraw" });
this.setState({ initialState: false });
};
let color = '';
return (
<Swipeable
renderLeftActions={LeftSwipeActions}
onSwipeableLeftWillOpen={swipeFromLeftOpen}
>
<View
style={{
backgroundColor: color == '' ? '#fff7da' : color,
borderRadius: 35,
flex: 0,
flexDirection: 'row',
alignItems: 'center'
}}
>
<View style={[styles.flex, styles.yellowSwiper]}>
<Image source={require('../../assets/images/dashboard/Rectangle431.png')} />
<Image source={require('../../assets/images/dashboard/Rectangle432.png')} />
<Image source={require('../../assets/images/dashboard/Rectangle433.png')} />
</View>
<Text style={{ fontSize: 20, fontWeight: 'bold', textTransform: 'uppercase', left: 50 }}>
Swipe to pay
</Text>
</View>
</Swipeable>
)
}
withdrawalMethod() {
return (
<View style={{ flex: 0, height: 570.40, backgroundColor: Colors.backgroundColor, margin: Sizes.fixPadding * 1.0, borderRadius: 20 }}>
<View style={{ padding: Sizes.fixPadding * 6.0 }}>
<Text style={styles.title}>
Select a Withdrawal Method
</Text>
</View>
<View>
<AppForm initialValues={{ withdrawal_method: '', authorization_mode: '' }} onSubmit={() => this.setState({ initialState: 1 })} validationSchema={validationSchema}>
<AppFormField dropDown={true} textValue={'Withdrawal Method'} name="withdrawal_method"
items={this.state.withdrawalMethod}
defaultValue={'-'}
disabled={this.state.initialLoading ? true : false}
onChange={(e) => this.setState({ withdrawMethodDesc: e })}
containerStyle={{ height: 60 }}
style={{ backgroundColor: Colors.backgroundColor, borderColor: '#adadad' }}
itemStyle={{
justifyContent: 'flex-start'
}}
dropDownStyle={{ backgroundColor: '#fafafa' }}
/>
{
this.state.withdrawMethodDesc != '' ?
<Text style={styles.methodDescription}>
Withdrawal Limit: {this.state.withdrawMethodDesc.min_limit} - {this.state.withdrawMethodDesc.max_limit} NGN,{'\n'}
Charge: {this.state.withdrawMethodDesc.charge} NGN
</Text>
:
null
}
<AppFormField dropDown={true} textValue={'Authorization mode'} name="authorization_mode"
items={this.state.authorizationMode}
defaultValue={'-'}
disabled={this.state.initialLoading ? true : false}
onChange={(e) => this.setState({ verification: e })}
containerStyle={{ height: 60 }}
style={{ backgroundColor: Colors.backgroundColor, borderColor: '#adadad' }}
itemStyle={{
justifyContent: 'flex-start'
}}
dropDownStyle={{ backgroundColor: '#fafafa' }}
/>
<AppButton text={'proceed'} />
</AppForm>
</View>
</View>
)
}
}
WithdrawScreen.navigationOptions = () => {
return {
header: () => null
}
}
export default withNavigation(WithdrawScreen);
const styles = StyleSheet.create({
flex: {
flex: 0,
flexDirection: 'row',
justifyContent: 'space-between'
},
trnsferDetCard: {
justifyContent: 'center',
backgroundColor: '#f4f2f6',
borderRadius: 20,
paddingVertical: 10,
paddingHorizontal: 20,
width: '100%',
height: 100,
marginVertical: 10,
},
screenContainer: {
flex: 1,
padding: 5,
backgroundColor: 'white'
},
textStyle: {
fontSize: 34,
fontWeight: 'bold',
color: '#476355'
},
userImage: { height: 70, width: 70, borderRadius: 27 },
inputAmount: {
flex: 0,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
inputIcon: {
color: "#E5E5E5",
fontSize: 45,
fontWeight: '600',
zIndex: 1
},
input:
{
height: 70,
borderBottomWidth: 1,
borderBottomColor: '#E5E5E5',
textAlign: 'center',
fontSize: 50,
fontWeight: '700',
textDecorationLine: 'none'
}
,
yellowSwiper: { width: 70, height: 70, borderRadius: 70, backgroundColor: '#fdd544', lineHeight: 70, alignItems: 'center', justifyContent: 'space-around', padding: 10 },
keys: { height: 71, width: 71, borderRadius: 71, borderWidth: 1, justifyContent: 'center', alignItems: 'center', borderColor: '#f4f6f5' },
title: { fontSize: 16, fontWeight: '500' },
methodDescription: {
color: Colors.dangerColor,
marginTop: -25,
paddingHorizontal: 20,
marginBottom: 35,
lineHeight: 25,
}
});
And this is the transactionPin screen
transactionPinScreen.js
import React, { Component } from "react";
import { Image, Text, View, StyleSheet, SafeAreaView, StatusBar, TouchableOpacity, TextInput, Dimensions, BackHandler } from "react-native";
import { withNavigation } from "react-navigation";
import { MaterialIcons, Feather } from '#expo/vector-icons';
import { Colors, Fonts, Sizes } from "../../constant/styles";
import TransferComplete from "../../component/transferComplete";
import dashApi from "../../api/dashApi";
import toast from "../../component/toaster";
import Loader from "../../component/Loader";
const { height, width } = Dimensions.get('screen');
let processing = false;
class TransactionPinScreen extends Component {
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton.bind(this));
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton.bind(this));
}
componentDidUpdate(prevProps) {
if (this.state.text.length == 4) {
(this.state.text)
? this.verify()
: console.log("Focused");
}
}
handleBackButton = () => {
this.props.navigation.pop();
return true;
};
onPress1 = () => {
this.pin('1')
}
onPress2 = () => {
this.pin('2')
}
onPress3 = () => {
this.pin('3')
}
onPress4 = () => {
this.pin('4')
}
onPress5 = () => {
this.pin('5')
}
onPress6 = () => {
this.pin('6')
}
onPress7 = () => {
this.pin('7')
}
onPress8 = () => {
this.pin('8')
}
onPress9 = () => {
this.pin('9')
}
onPress0 = () => {
this.pin('0')
}
onPressBackspace = () => {
let text = this.state.text.slice(0, this.state.text.length - 1);
this.setState({ text: text })
}
pin(val) {
this.state.text.length != 4 ? this.setState({ text: this.state.text + val }) : null;
}
constructor(props) {
super(props)
this.state = {
text: '',
completeScreen: false,
processing: processing ?? false,
};
this.verify = this.verify.bind(this)
}
verify = () => {
// For Withdrawal code is 2, Transfer is 1;
var pinLenght = this.state.text.length;
// console.log(pinLenght, this.state.text, this.props.navigation.state.params);
if (pinLenght == 4) {
console.log(this.state.text);
const data = {
...this.props.navigation.state.params ?? null,
pin: this.state.text,
}
data.type == 'withdraw' ? this.makeWithdraw(data)
: this.transfer(data);
}
}
makeWithdraw = async (data) => {
console.log('prod');
this.setState({ processing: true });
const result = await dashApi.withdrawal(data);
if (result.status == 200) {
this.setState({ processing: false });
this.setState({ completeScreen: 1 });
}
else if (result.status == 401 || result.data.data == null) {
// this.setState({ errorText: result.data.message });
toast('red', result.data.message);
this.setState({ processing: false });
}
else {
this.setState({ processing: false });
// this.setState({ errorText: 'Network Error' })
}
console.log(result);
}
transfer = async (data) => {
// this.setState({ processing: true });
const result = await dashApi.transfer(data);
let output;
if (result.status == 200) {
// output = {success: 200};
this.setState({ processing: false });
this.setState({ completeScreen: 1 });
}
else if (result.status == 401) {
// output = {error: result.data.message};
this.setState({ outputText: { error: result.data.message } });
this.setState({ processing: false });
}
else if (result.status == 422) {
// output = {error: result.data.message}
this.setState({ outputText: 'Network output' })
}
let finale = { output: output }
console.log(finale, result);
return finale;
}
render() {
return (
<View>
<SafeAreaView style={this.state.completeScreen == true ? [{ backgroundColor: 'white', flex: 1, alignSelf: "center", alignItems: 'center' }] : styles.screenContainer}>
<StatusBar backgroundColor={Colors.backgroundColor} barStyle="dark-content" />
{
this.state.completeScreen == false ?
<View>
{this.iconText()}
{this.buttonKeyboardMode()}
</View>
:
<View>
<TransferComplete showing={true} onPress={() => this.props.navigation.navigate('Dashboard')} buttonText="Done" subtitle="Your transaction is processing. Payment is usually completed within a minute." />
</View>
}
</SafeAreaView>
</View>
)
}
iconText() {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', paddingTop: 50 }}>
<Image source={require('../../assets/images/dashboard/fingerPrint.png')} style={styles.fingerTip} />
<Text>enter pin code or use fingerprint</Text>
<Loader loading={this.state.processing} />
<View style={styles.searchSection}>
<TouchableOpacity style={styles.searchIcon} onPress={() => this.onPressBackspace()} >
<MaterialIcons name="backspace" size={24} color="black" />
</TouchableOpacity>
<TextInput
style={styles.input}
value={this.state.text}
secureTextEntry
// onChange={() => this.verify()}
maxLength={4}
underlineColorAndroid="transparent"
showSoftInputOnFocus={false}
autoFocus
caretHidden={true}
/>
</View>
</View>
)
}
buttonKeyboardMode() {
return (
<View style={{ paddingHorizontal: 40, paddingTop: 20, paddingBottom: 50 }}>
<View style={[styles.flex, { marginBottom: 15 }]}>
<TouchableOpacity style={styles.keys} onPress={this.onPress1}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>1</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress2}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>2</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress3}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>3</Text>
</TouchableOpacity>
</View>
<View style={[styles.flex, { marginBottom: 15 }]}>
<TouchableOpacity style={styles.keys} onPress={this.onPress4}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>4</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress5}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>5</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress6}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>6</Text>
</TouchableOpacity>
</View>
<View style={[styles.flex, { marginBottom: 15 }]} >
<TouchableOpacity style={styles.keys} onPress={this.onPress7}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>7</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress8}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>8</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.keys} onPress={this.onPress9}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>9</Text>
</TouchableOpacity>
</View>
<View style={[styles.flex, { marginBottom: 15, alignSelf: 'center' }]}>
<TouchableOpacity style={styles.keys} onPress={this.onPress0}>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>0</Text>
</TouchableOpacity>
</View>
</View>
)
}
completeScreen() {
// console.log(height, width);
return (
<View style={[styles.flex, { justifyContent: 'center', top: 250 }]}>
<View style={{ width: 100, height: 100, borderRadius: 100, backgroundColor: 'yellow', justifyContent: 'center', alignItems: 'center' }}>
<MaterialIcons name="check" size={80} color="white" />
</View>
</View>
)
}
export default withNavigation(TransactionPinScreen);
const styles = StyleSheet.create({
flex: {
flex: 0,
flexDirection: 'row',
justifyContent: 'space-between'
},
screenContainer: {
flex: 0,
padding: 5,
backgroundColor: 'white',
},
fingerTip: { tintColor: '#83968c', width: 58.37, height: 56.73, marginBottom: 45.7 },
searchSection: {
flex: 0,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#fff',
marginVertical: 20,
},
searchIcon: {
position: 'absolute',
left: 240,
zIndex: 1
},
input:
{ width: 284, borderRadius: 10, backgroundColor: '#f7f7f7', textAlign: 'center', fontSize: 50, fontWeight: '700' }
,
keys: { height: 71, width: 71, borderRadius: 71, borderWidth: 1, justifyContent: 'center', alignItems: 'center', borderColor: '#f4f6f5' },
});

ERROR : undefined is not an object (evaluation 'style.width')

Hello everyone I'm having trouble with component and I get an undefined error message.So my app has 2 screen,the first one has a list of imagebackgrounds and when you press on one of the images you get a description of that image on another screen.So on this second screen I get the image that I pressed on in an image component (not background).
The problem I'm having is that when I save I get the undefined error.
First screen component :
const MealItems = (props) => {
return (
<View style={styles.main}>
<TouchableOpacity onPress={props.onSelectMeal}>
<View>
<View style={{ ...styles.details, ...styles.maintitle }}>
<ImageBackground
//resizeMode={"center"}
source={{ uri: props.image }}
style={styles.imagebg}
>
<View style={styles.textContainer}>
<Text style={styles.title} numberOfLines={1}>
{props.title}
</Text>
</View>
</ImageBackground>
</View>
<View style={{ ...styles.details, ...styles.info }}>
<Text>{props.duration}</Text>
<Text>{props.complexity.toUpperCase()}</Text>
<Text>{props.affordability.toUpperCase()}</Text>
</View>
</View>
</TouchableOpacity>
</View>
);
};
styles = StyleSheet.create({
main: {
height: 200,
width: "100%",
backgroundColor: "#f5f5f5",
borderRadius: 20,
overflow: "hidden",
marginVertical: 10,
},
maintitle: {
height: "85%",
},
title: {
fontSize: 20,
color: "white",
textAlign: "center",
},
details: {
flexDirection: "row",
},
imagebg: {
width: "100%",
height: "100%",
},
info: {
backgroundColor: "gray",
paddingHorizontal: 10,
justifyContent: "space-between",
alignItems: "center",
height: "15%",
},
textContainer: {
paddingHorizontal: 12,
paddingVertical: 10,
backgroundColor: "rgba(0,0,0,0.3)",
},
});
export default MealItems;
***Second screen file:***
const howToCook = (props) => {
const availableMeals = useSelector((state) => state.Meals.filteredMeals);
const mealId = props.navigation.getParam("mealId");
const selectedMeal = availableMeals.find((meal) => mealId === meal.id);
return (
<ScrollView>
<Image source={{ uri: selectedMeal.imageUrl }} style={styles.image} />
<View style={styles.textDetail}>
<Text>{selectedMeal.duration}</Text>
<Text>{selectedMeal.complexity.toUpperCase()}</Text>
<Text>{selectedMeal.affordability.toUpperCase()}</Text>
</View>
<View style={styles.titlePlace}>
<Text style={styles.textTitle}>Ingredients</Text>
</View>

FlatList RefreshControl not working on Android

I have a FlatList inside of a view and I'm unable to get the refresh control working on Android emulators/devices.
I have tried many solutions but to no luck. Any help or suggestions would be greatly appreciated.
Code:
onPullToRefresh = () => {
this.props.onRefreshData();
}
...
render() {
const isRefreshing = this.props.refreshing['entities'] ? this.props.refreshing['entities'] : false;
...
{!this.state.favoritesExpand &&
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<FlatListCustom
style={{ flex: 1, flexDirection: 'column' }}
data={this.state.searchString && this.state.searchString.length > 0 ? this.state.searchMatchedItems : this.state.items}
renderItem={this.renderEntityItem}
keyExtractor={(item) => item.id}
extractData={this.state.selectedItemId}
windowSize={1}
ref={ref => this.itemScrollViewRef = ref}
getItemLayout={this.getItemLayout}
refreshControl={
<RefreshControl refreshing={isRefreshing} onRefresh={this.onPullToRefresh} />
}
/>
{(screenMaster == 'investor' || screenMaster == 'asset') &&
<View style={{ position: 'absolute', right: 0, top: 0, justifyContent: 'space-between', flex: 1, flexDirection: 'column', height: '100%', paddingTop: 8, paddingBottom: 20 }}>
{this.state.AZList.map(item => (
<Touch
key={`AZList_${item}`}
onPress={() => this.onAZListSelect(item)}
>
<Text style={{ textAlign: 'center', color: '#006dc4', fontSize: Platform.isPad ? normalize(7) : normalize(12), paddingHorizontal: 10, fontWeight: 'bold', fontFamily: "Geogrotesque" }}>{item}</Text>
</Touch>
))}
</View>
}
</View>
}

React-Native .js Variable not found error

Cannot figure out why I keep getting a ReferenceError cant find variable MarkAsRead for a mobile app I am building in react. Unless I am missing something the variable has been assigned below is the code for your reference. Hopefully, someone can help me get this bug resolved in a timely matter thanks in advance!
import React from 'react';
import { View,
Text,
StyleSheet,
SafeAreaView,
TouchableOpacity,
TextInput,
FlatList
} from 'react-native';
import BookCount from './components/BookCount';
import {Ionicons} from '#expo/vector-icons';
class App extends React.Component {
constructor() {
super()
this.state = {
totalCount: 0,
readingCount: 0,
readCount: 0,
isAddNewBookVisible:false,
textInputData: '',
books: [],
bookData: {
author: '',
publisher: ''
}
};
}
showAddNewBook = () => {
this.setState({isAddNewBookVisible:true});
};
hideAddNewBook = () => {
this.setState({isAddNewBookVisible:false})
};
addBook = book => {
this.setState(
(state, props) => ({
books: [...state.books, book],
totalCount: state.totalCount + 1,
readingCount:state.readingCount + 1,
isAddNewBookVisible: false
}),
() => {
console.log(this.state);
}
);
};
markAsRead = (selectedBook, index) => {
let newList = this.state.books.filter(book => book !==
selectedBook);
this.setState(prevState => ({
books: newList,
readingCount: prevState.readingCount - 1,
readCount: prevState.readCount + 1
}));
};
renderItem = (item, index) => (
<View style={{ height:50, flexDirection: 'row'}}>
<View style={{ flex:1, justifyContent: 'center', paddingLeft: 5
}}>
<Text>{item}</Text>
</View>
<TouchableOpacity onPress={() => markAsRead(item,index)} >
<View
style={{
width: 100,
height: 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#160b1a'
}}
>
<Text style={{ fontWeight: 'bold', color: 'white'}}>Mark as Read</Text>
</View>
</TouchableOpacity>
</View>
);
render() {
return (
<View style={{flex: 1}}>
<SafeAreaView/>
<View style={{
height: 70,
borderBottomWidth: 0.5,
borderBottomColor: '#5e3c7d',
alignItems: 'center',
justifyContent: 'center'
}}
>
<Text style={{fontSize: 24}}>VekTorfy AI</Text>
</View>
<View style={{ flex: 1}}>
{this.state.isAddNewBookVisible &&
<View style={{height:50, flexDirection: 'row'}}>
<TextInput
onChangeText={(text)=>this.setState({textInputData:text})}
style={{ flex:1, backgroundColor: '#c6c0cb',
paddingLeft: 5}}
placeholder='Enter book name.'
placeholderTextColor='black'
/>
<TouchableOpacity
onPress={() => this.addBook(this.state.textInputData)} >
<View style={{
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#160b1a'}}>
<Ionicons name ='ios-checkmark' color='white' size={40}/>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={this.hideAddNewBook}>
<View style={{
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#160b1a'}}>
<Ionicons name ='ios-close' color='red' size={40}/>
</View>
</TouchableOpacity>
</View>
}
<FlatList
data={this.state.books}
renderItem={({item}, index) => this.renderItem(item, index)}
keyExtractor={(item, index)=> index.toString()}
ListEmptyComponent={
<View style={{marginTop: 50, alignItems: 'center'}}>
<Text style={{fontWeight: 'bold'}}>Not Reading anything.</Text>
</View>
}
/>
<TouchableOpacity
onPress={this.showAddNewBook}
style={{position: 'absolute', bottom: 20, right: 20}}>
<View
style={{
width:50,
heght:50,
alignItems: 'center',
justifyContent: 'center',
borderRadius:25,
backgroundColor: '#2d2337'}}>
<Text style={{color: 'white', fontSize: 30}}>+</Text>
</View></TouchableOpacity>
</View>
<View
style={{
height: 70,
flexDirection: 'row',
borderTopWidth: 0.5,
borderTopColor: '#5e3c7d' }}>
<BookCount title='Total' count={this.state.totalCount}/>
<BookCount title='Reading' count={this.state.readingCount}/>
<BookCount title='Read' count={this.state.readCount}/>
</View>
<SafeAreaView/>
</View>
);
}
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
You forgot to add the keyword this to your function call.
<TouchableOpacity onPress={() => this.markAsRead(item,index)}>
It looks like you have declared markAsRead as a method on your App class, so the correct way to refer to it is this.markAsRead()
<TouchableOpacity onPress={() => this.markAsRead(item, index)}>

Add Custom createMaterialTopTabNavigator to component?

I have an issue with createMaterialTopTabNavigator,
I'm already declaring an AppContainer in my Route.js File,
the error goes away if create a separate AppContainer for a TobTab in a screen I want to add these Tob Tabs in
like this
const Root = createAppContainer(NavTabs);
so I made a specific file contained a Tabs "NavTabs.js"
import { createMaterialTopTabNavigator } from "react-navigation";
import AboutScreen from "./About";
import GalaryScreen from "./Galary";
import ReviewsScreen from "./Reviews";
const NavTabs = createMaterialTopTabNavigator(
{
About: { screen: AboutScreen },
Galaty: { screen: GalaryScreen },
Reviews: { screen: ReviewsScreen }
},
{
tabBarOptions: {
activeTintColor: "#fff",
inactiveTintColor: "#ddd",
tabStyle: {
justifyContent: "center"
},
indicatorStyle: {
backgroundColor: "#fcc11e"
},
style: {
backgroundColor: "#347ed8"
}
}
}
);
export default NavTabs;
and in the File navigations "Route.js" I put it in the StackNavigator like this
and here the full File
const HomeStack = createStackNavigator({
Home: {
screen: Home,
navigationOptions: ({ navigation }) => ({
title: "Home",
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerRight: (
<TouchableOpacity
onPress={() => navigation.navigate("Notifications")}
style={{ margin: 10 }}
>
<Icon name="ios-notifications" size={28} color="#1DA1F2" />
</TouchableOpacity>
),
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1,
marginBottom: 20
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
})
},
MapScreen: {
screen: MapScreen,
navigationOptions: {
title: "Map",
headerRight: <View />,
// headerLeft: <View />,
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1,
marginBottom: 0
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
}
},
ProviderProfile: {
screen: ProviderProfile,
navigationOptions: {
headerRight: <View />,
// headerLeft: <View />,
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
}
},
Order: {
screen: Order,
navigationOptions: {
title: "Order",
headerRight: <View />,
// headerLeft: <View />,
headerTintColor: "#fff",
headerStyle: {
backgroundColor: "#fff",
shadowOpacity: 0,
elevation: 1
},
headerTintColor: "#14171a",
headerTitleStyle: {
flex: 1,
fontSize: 25,
justifyContent: "center"
}
}
},
Tabs: NavTabs
});
and when I Import it in my screen " profile"
like this
<View>
<View style={{ flexDirection: "row", marginTop: 10 }}>
<TouchableOpacity
style={{
backgroundColor: "#1567d3",
width: 130,
borderRadius: 100,
justifyContent: "center",
marginRight: 50,
height: 40
}}
onPress={() => alert("Message")}
>
<Text
style={{
textAlign: "center",
color: "#fff",
fontSize: 18,
fontWeight: "300"
}}
>
Message
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: "#1567d3",
width: 130,
borderRadius: 100,
justifyContent: "center",
height: 40
}}
onPress={() =>
this.props.navigation.navigate("Order", {
providerName,
providerId,
providerService,
gKey,
token,
region
})
}
>
<Text
style={{
textAlign: "center",
color: "#fff",
fontSize: 18,
fontWeight: "300"
}}
>
Send Order
</Text>
</TouchableOpacity>
</View>
<NavTabs />
</View>
I got the error like above, so how to handle this without making the other app container?
cuz when i navigate from Map screen to Profile screen i pass some Params and i want to use these params in the Tabs
this.props.navigation.navigate('ProviderProfile', {
providerId: marker.id,
providerName: marker.name,
providerService: marker.service,
gKey: marker.gKey,
token: marker.token._55,
region: region
})
the result should be like this " as you see i have a name "Loy" i wanna use it in About Tab"

Categories

Resources