React Native move navigator text - reactjs

Hey In react native I'm using and Everything works well so far but the title and the back button text don't line up. (The login is higher then register) Any ideas how I could set this up?
render() {
const titleConfig = {
title: 'login',
tintColor: "white",
}
return(
<View style={styles.bb}>
<NavigationBar
title={titleConfig}
tintColor="black" />
</View>
)
}

You can pass in a react element to title prop with styling to make it align as per your requirements. For e.g:
render() {
const title = <View style={styles.navTitle}>
<Text style={styles.navTitleText}>Login</Text>
</View>;
return (
<View style={styles.bb}>
<NavigationBar
title={title}
tintColor="black"
/>
</View>
);
}
var styles = StyleSheet.create({
navTitleText: {
color: "white",
fontSize: 19,
marginBottom: 4,
}
});
Here's the complete guide about the API https://github.com/react-native-fellowship/react-native-navbar#api

Related

Update Progress bar value when end scrolling in ScrollView on React Native

I have created a functionality , In which show the Progress bar and it's value change according to scrolling the view. the progress bar value should depend that scrolling is end or not if the scrolling is end then the progress bar should completely filled.
I have tired but it's not working. Here my code:
import React, {useState, useEffect} from 'react';
import * as Progress from 'react-native-progress';
import { Card } from 'react-native-paper';
import { Text, View, StyleSheet,ScrollView } from 'react-native';
const scrollView_height = 0;
const scrollViewContent_height = 0;
export default function App() {
const UpdateProgressBar = (progress) => {
setProgress(
Math.abs(
progress.nativeEvent.contentOffset.y /
(scrollViewContent_height - scrollView_height),
),
);
};
return (
<View style={styles.container}>
<Progress.Bar
style={{
position: 'relative',
bottom: 6,
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
}}
height={3}
borderWidth={0}
progress={progress_count}
color="red"
width={widthToDp('82%')}
/>
<ScrollView
showsVerticalScrollIndicator={false}
bounces={false}
contentContainerStyle={{paddingBottom: 0}}
onContentSizeChange={(width, height) => {
scrollViewContent_height = height;
}}
onScroll={UpdateProgressBar}
onLayout={(event) =>
(scrollView_height = event.nativeEvent.layout.height)
}
scrollEventThrottle={12}>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Card>
<AssetExample />
</Card>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
}
});
Please Suggest the Solution.
import React, {useState, useEffect} from 'react';
import * as Progress from 'react-native-progress';
import { Card } from 'react-native-paper';
import { Text, View, StyleSheet,ScrollView } from 'react-native';
export default function App() {
const [scrollView_height, setScrollView_height] = useState(0)
const [scrollViewContent_height, setScrollViewContent_height] = useState(0)
const [progress, setProgress] = useState(0)
const UpdateProgressBar = (value) => {
setProgress(
Math.abs(
value.nativeEvent.contentOffset.y /
(scrollViewContent_height - scrollView_height),
),
);
};
return (
<View style={styles.container}>
<Progress.Bar
style={{
position: 'relative',
bottom: 6,
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
}}
height={3}
borderWidth={0}
progress={progress}
color="red"
width={widthToDp('82%')}
/>
<ScrollView
showsVerticalScrollIndicator={false}
bounces={false}
contentContainerStyle={{paddingBottom: 0}}
onContentSizeChange={(width, height) => {
setScrollView_height(height);
}}
onScroll={UpdateProgressBar}
onLayout={(event) =>
setScrollView_height(event.nativeEvent.layout.height)
}
scrollEventThrottle={12}>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a
shareable url.
</Text>
<Card>
<AssetExample />
</Card>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
}
});

Conditional rendering cannot be seen due to a return before them

Please help give me a better title, I couldn't word what I am asking.
To understand my question I have to provide some context of my project. Originally I wanted to conditionally render two pages through two buttons. Button A rendering screen A and button B rendering screen B. After figuring out how to pass the state from a parent component to a child and its child etc, I changed my button to a sliding animation for better design.
This causes issues because now when a new screen is rendered, the animation does not show because it is simply re-rendered with the original starting place in the animation(I rendered the slider through each screen). I thought about providing two different sliders, each starting in the opposing opposition but that would still lose the entire slide effect.
I have now resulted to rendering the Slider so it is there all the time and is not re-rendered. However I have realized now that if I return it before my conditionals, that code is never reached. I have provided a working demo that shows my problem perfectly as well as the code below(I only provided App.js, the rest is on the demo if needed). I want to render Slider in App.js.
The working demo is here, you can see the slider does not slide, it just changes screens. I need it to slide. Also the sliding animation only works on iphone so I would use that emulator rather than the web.
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
whichComponentToShow: "Screen1"
};
}
goToMap = () => {
this.setState({ whichComponentToShow: "Screen2" });
};
goToList = () => {
this.setState({ whichComponentToShow: "Screen1" });
};
render() {
const { whichComponentToShow } = this.state;
/* This is how I thought I could render this, but obv it makes the rest of the code unreachable.
How can I render this and then have the conditional page below? Each time the new page renders,
it stops the animation from working due to rendering the new page.
return(
<Slider/>
)*/
if(this.state.whichComponentToShow === 'Screen1'){
return(
<View style={{backgroundColor: '#d1cfcf' ,flex: 1}}>
<ListHome
renderMap = {this.goToMap.bind(this)}
renderList = {this.goToList.bind(this)}
/>
</View>
);
}
else if(this.state.whichComponentToShow === 'Screen2'){
return(
<View style={{backgroundColor: '#d1cfcf' ,flex: 1}}>
<MapHome
renderMap = {this.goToMap.bind(this)}
renderList = {this.goToList.bind(this)}
/>
</View>
);
}
Slider.js (wont show up on the snack apparently
const Slider = (props) => {
const [active, setActive] = useState(false)
let transformX = useRef(new Animated.Value(0)).current;
useEffect(() => {
if (active) {
Animated.timing(transformX, {
toValue: 1,
duration: 300,
useNativeDriver: true
}).start()
} else {
Animated.timing(transformX, {
toValue: 0,
duration: 300,
useNativeDriver: true
}).start()
}
}, [active]);
const rotationX = transformX.interpolate({
inputRange: [0, 1],
outputRange: [2, Dimensions.get('screen').width / 4]
})
return (
<SafeAreaView style={{
flex: 1,
alignItems: 'center'
}}>
<View style={{
flexDirection: 'row',
position: 'relative',
height: 45,
width: 240,
borderRadius: 10,
backgroundColor: 'white',
marginHorizontal: 5
}}>
<Animated.View
style={{
position: 'absolute',
height: 45 - 2*2,
top: 2,
bottom: 2,
borderRadius: 10,
width: Dimensions
.get('screen').width / 3 - 3.5 ,
transform: [
{
translateX: rotationX
}
],
backgroundColor: '#d1cfcf',
}}
>
</Animated.View>
<TouchableOpacity style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}} onPress={() => {setActive(false); props.renderList() }}>
<Text>
List
</Text>
</TouchableOpacity>
<TouchableOpacity style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}} onPress={() => {setActive(true); props.renderMap() }}>
<Text>
Map
</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
export default Slider
I tried your expo snack and saw no code related to animation, so I'm assuming the code in the snack isn't your current code, and that you really do already have a working, animated, <Slider ... />.
In your situation, what you could do to keep your Slider rendered and not unmounted, is to use variables in the render() method.
Basically, you can assign the <Slider .../> JSX to a variable, and you can use that variable in another JSX part later.
Assigning a key to the specific JSX also helps guide React that this is the same component between render calls, so it also prevents unintentional rerenders of that component.
Here's an edit with comments from what you wrote in your post. I hope this makes sense.
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
whichComponentToShow: "Screen1"
};
}
goToMap = () => {
this.setState({ whichComponentToShow: "Screen2" });
};
goToList = () => {
this.setState({ whichComponentToShow: "Screen1" });
};
render() {
const { whichComponentToShow } = this.state;
/*
Keep the slider JSX in a variable to be used.
Setting a specific key also helps prevent it from being accidentally re-rendered in some conditions.
)*/
const sliderRender = <Slider key='slider' />;
if (this.state.whichComponentToShow === 'Screen1') {
return (
<View style={{ backgroundColor: '#d1cfcf', flex: 1 }}>
<ListHome
renderMap={this.goToMap.bind(this)}
renderList={this.goToList.bind(this)}
/>
{/* Put the rendered slider into the render tree */}
{sliderRender}
</View>
);
}
else if (this.state.whichComponentToShow === 'Screen2') {
return (
<View style={{ backgroundColor: '#d1cfcf', flex: 1 }}>
<MapHome
renderMap={this.goToMap.bind(this)}
renderList={this.goToList.bind(this)}
/>
{/* Put the rendered slider into the render tree */}
{sliderRender}
</View>
);
}
}
}
Edit : Expo Snack demonstrating it working

Text strings must be rendered within a <Text> component

Please what is wrong with this code.I have removed all white spaces. I have checked for semi colons in the code. I still have the same error.
I read before that it could happen because of white empty spaces but I don't see any empty white spaces in my code below. I have edited the question.
import React, { Component } from 'react';
import { StyleSheet, ScrollView, View } from 'react-native';
import { List, ListItem, Text, Card } from 'react-native-elements';
class DetailsScreen extends Component {
static navigationOptions = {
title: 'Details',
};
render() {
const { navigation } = this.props;
const matches = JSON.parse(navigation.getParam('matches', 'No matches found'));
console.log(matches)
return (
<ScrollView>
<Card style={styles.container}>
{
matches.map((item, key) => (
<View key={key} style={styles.subContainer}>
<View>
<Text style={styles.baseText}>{item.group}</Text>
</View>
<View>
<Text style={styles.baseText}>{item.team1.name}</Text>
<Text>{item.team2.name}</Text>
</View>
<View>
<Text style={styles.baseText}>{item.date}</Text>
</View>
<View>
<Text style={styles.baseText}>{item.score1}</Text>
<Text>{item.score2}</Text>
</View>
if(item.goals1.length > 0) {
item.goals1.map((item2, key2) => (
<View key={key2}><Text style={styles.baseText}>{item2.name} {item2.minute}</Text></View>
))
}
if(item.goals2.length > 0) {
item.goals2.map((item3, key3) => (
<View key={key3}><Text style={styles.baseText}>{item3.name} {item3.minute}</Text></View>
))
}</View>
))
}
</Card>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20
},
subContainer: {
flex: 1,
paddingBottom: 20,
borderBottomWidth: 2,
borderBottomColor: '#CCCCCC'
},
baseText:{
fontFamily:'Cochin',
fontSize:14,
fontWeight:'bold'}
})
export default DetailsScreen;
remove h2, h3, h3 from Text components since it has no props (not fatal, but useless) and you dont need () here either ({item2.minute}) which actually breaks the code
i suggest also checking out what props and methods Text component have here:
https://facebook.github.io/react-native/docs/text.html
hope this helps
Agree with wijuwiju's answer also do not nest other elements including <Text> inside a <Text> component. It will mostly create problems even if now on one platform you don't see any problems.

Detect active screen in React Native

Sorry for my bad English. I have built a navigation bar without using Tab Navigation from React Navigation, everything works fine except when I try to set an 'active' icon, I have handled it with states but the state restarts when I navigate to another window and render the bar again navigation.
I think I have complicated it a bit, but I need to capture the active screen to pass it as status and change the color of the icon to 'active' and the others disabled. I have tried with Detect active screen and onDidFocus but I only received information about the transition, I require the name or id of the screen.
I leave my code (this component is exported to each page where I wish to have the navigation bar). Please, the idea is to not use Tab Navigation from React Native Navigation.
export default class Navbar extends Component {
/** Navigation functions by clicking on the icon (image) */
_onPressHome() {
this.props.navigation.navigate('Main');
}
_onPressSearch() {
this.props.navigation.navigate('Main');
}
render() {
const { height, width } = Dimensions.get('window');
return (
<View style={{ flexDirection: 'row', height: height * .1, justifyContent: 'space-between', padding: height * .02 }}>
/** Icon section go Home screen */
<View style={{ height: height * .06, alignItems: 'center' }}>
<TouchableOpacity
onPress={() => this._onPressHome()}
style={styles.iconStyle}>
<Image
source={HOME_ICON}
style={{ width: height * .04, height: height * .04, }} />
<Text style={[styles.footerText, { color: this.state.colorA }]}>Inicio</Text>
</TouchableOpacity>
</View>
/** Icon section go Search screen */
<View style={{ height: height * .06, alignItems: 'center' }} >
<TouchableOpacity
onPress={() => this._onPressSearch()}
style={styles.iconStyle}>
<Image
source={SEARCH_ICON}
style={{ width: height * .04, height: height * .04, opacity: .6 }} />
<Text style={[styles.footerText, { color: this.state.colorB }]}>Inicio</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
For the navigation I used createStackNavigator and also
const drawerNavigatorConfig = {
contentComponent: props => <CustomDrawerContentComponent {...props}
/>,
};
const AppDrawer = createDrawerNavigator(drawerRouteConfig,
drawerNavigatorConfig);
I do not know if createDrawerNavigator is interfering with something, I read that it generates additional keys. Please help me with this.
import { useIsFocused } from '#react-navigation/native';
function Profile() {
const isFocused = useIsFocused();
return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
}
check documentation
https://reactnavigation.org/docs/use-is-focused/
You can use this inViewPort library for checking the view port of the user. This is how you can user the library
render(){
<InViewPort onChange={(isVisible) => this.checkVisible(isVisible)}>
<View style={{flex: 1, height: 200, backgroundColor: 'blue'}}>
<Text style={{color: 'white'}}>View is visible? {this.state.visible </Text>
</View>
</InViewPort>
}

Navigator, persist footer&header between transition

The Navigator has props for a navigationBar. The docs say:
"Optionally provide a navigation bar that persists across scene transitions"
Using that, when there is a transition to a new screen, only the content will get animated while the navigation bar doesn't change, i.e. it persists.
However, using the navigationBar props I can either have a header OR a footer that persists across transitions. I would like to have both: Header and Footer should both persist across scene transitions.
I've added an example here:
RN Play Example
If you click on 'TestComponent' or 'TestComponent2' you will see the next screen transition in from the right while the navbar at the bottom is NOT part of the transition. How can I add a header that will also NOT be part of the transition?
Is that possible with the navigator?
We've not found a good solution to this so we rolled our own and it has actually worked very very well in a fairly complex app. Here is the gist of what our custom navigator component looks like:
var App = React.createClass({
render() {
return (
<View style={{ flex:1 }}>
<Header />
<AppNavigator />
<Footer />
</View>
)
}
})
The great thing about this is that we have a lot of control over the header and footer. I've set up a basic working example of what I'm talking about here, and pasted the code below.
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableHighlight
} = React;
var Header = () => (
<View style={ styles.nav }>
<Text>PERSISTENT Header</Text>
</View>
)
var Footer = () => (
<View style={ styles.footer }>
<Text>PERSISTENT Footer</Text>
</View>
)
var AppNavigator = React.createClass({
renderScene(route, navigator) {
return React.createElement(route.component, { ...this.props, ...route.passProps, navigator, route } )
},
render() {
return (
<Navigator
style={{ flex:1 }}
initialRoute={{ id: '0', component: Home, title: 'Home' }}
renderScene={ this.renderScene }
/>
)
},
})
var App = React.createClass({
render() {
return (
<View style={{ flex:1 }}>
<Header />
<AppNavigator />
<Footer />
</View>
)
}
})
var Home = React.createClass({
navigate(route, someprops) {
this.props.navigator.push({
component: route,
passProps: {
someprops: someprops
}
})
},
render: function() {
return (
<View style={styles.container}>
<Text>Hello from Home</Text>
<TouchableHighlight onPress={ () => this.navigate(About, 'ABOUT MESSAGE!!!') } style={ styles.button }>
<Text>Go to about</Text>
</TouchableHighlight>
</View>
);
}
});
var About = React.createClass({
render() {
return (
<View>
<Text>HEllo from About</Text>
<Text>These are the props: { this.props.someprops }</Text>
</View>
)
}
})
var styles = StyleSheet.create({
container: {
flex: 1,
},
button: {
height:50,
backgroundColor: '#efefef',
borderWidth:1,
borderColor: '#ededed'
},
nav: {
height: 60,
backgroundColor: '#ededed',
alignItems: 'center',
justifyContent: 'center'
},
footer: {
height: 60,
backgroundColor: '#ededed',
alignItems: 'center',
justifyContent: 'center'
}
});
AppRegistry.registerComponent('App', () => App);

Resources