I'm using react-native-navigation library on my project and i'm having some issues with my status bar. First one is that i'm unable to change my status bar background color on iOS, so i created a component for that as follow:
const S_StatusBar = ({ backgroundColor, ...props }) => (
<View style={[styles.statusBar, { backgroundColor }]}>
<StatusBar translucent backgroundColor={backgroundColor} {...props} />
</View>
);
const STATUSBAR_HEIGHT = Platform.OS === 'ios' ? 20 :
StatusBar.currentHeight;
const styles = StyleSheet.create({
statusBar: {
height: STATUSBAR_HEIGHT,
}
});
I import this component on all my screen as followed:
<View>
<S_StatusBar backgroundColor="#090b4b" barStyle="light-content" />
</View>
Here is how i push my screen using the react-native-navigation library:
pushProductDetailScreen = () => {
this.props.navigator.push({
screen: 'cfl.ProductDetail'
});
};
The screen is pushed correctly but now my problem is that my status bar is under my navigation bar such as followed:
I don't understand the issue and why it's happening!
You are creating a View encapsulating something
<View style={[styles.statusBar, { backgroundColor }]}>
...
</View>
statusBar: {
height: STATUSBAR_HEIGHT,
}
So it does create a View with the specified height and backgroundColor
StatusBar is a component a bit different. It doesn't render anything but change the settings of your StatusBar.
You should be able to configure it from your View itself
<StatusBar
backgroundColor="blue"
barStyle="light-content"
/>
This styling works for me
const STATUSBAR_HEIGHT = Platform.OS === 'ios' ? 20 : 0;
class App extends Component {
render() {
return (
<View style={[styles.container]}>
<View style={[styles.statusbar]}>
<StatusBar barStyle="dark-content"/>
</View>
<WebView
style={[styles.webview]}
source={{ uri: "https://..." }}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
},
statusbar: {
height: STATUSBAR_HEIGHT,
},
webview: {
flex: 1,
}
});
Related
I have made a custom button and below is the code.
export class MenuItems extends Component {
constructor(props) {
super(props);
this.state = {
loading: true
};
}
render() {
let { navigation, listingname, imagesource,} = this.props;
return (
<View >
<TouchableOpacity
onPress={this.props.onPress}
style={[styles.menuStyle]}>
<View style={{ flexDirection: 'row', }}>
<Image source={imagesource} style={[styles.menuItemIcon,{tintColor:'black'}]} />
<Text style={[styles.menuTextstyle]}>{listingname} </Text>
</View>
</TouchableOpacity>
</View>
);
}
}
export default MenuItems;
Now I have reused it with different value and images . I want to change the tint color and text color of the custom button to blue . Below is the code.
\<MenuItems listingname="Logout"
onPress={() => {
this.RBSheet.close();
// this.props.navigation.replace('HomeApp', { screen: 'Home' })
// navigation.dispatch(StackActions.popToTop());
// reset Notification counter
this.props.notifyCountrUpdtHndlr(0)
AuthHelpers.logout(this.props.navigation, true);
}}
imagesource ={IMAGE.LOGOUT_ICO}/>
</View>
I want the image color in blue using tint color and text color of the component in blue. kindly provide the solution and correct the code.
Use style
const StyledImage = ({style}) =>
<Image
style={{width: 20, height: 20, ...style}}
...
/>
<StyledImage style={{tintColor: 'blue'}} />
or custom prop
const TintedImage = ({tintColor}) =>
<Image
style={{width: 20, height: 20, tintColor: tintColor}}
...
/>
<TintedImage tintColor='red' />
I am using RN 0.59. Every time I placed the app on the background then reopen it immediately, the SafeAreaView does not take the whole screen.
But, if I placed the app on the background and reopen it after a while (for about 3 seconds) it is working fine.
Here's my snippet on SafeAreaView
...
const SafeAreaViewUI = ({children}) => {
return (
<SafeAreaView style={styles.container}>
<View style={styles.content}>
{ children }
</View>
</SafeAreaView>
);
};
...
export default SafeAreaViewUI;
for my styling
container: {
flex: 1,
backgroundColor: Platform.OS === 'android' ? blurple : null,
paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,
},
content: {
flexGrow: 1,
color: text,
backgroundColor: white,
}
Any insight for this one?
This worked on my end.
const SafeAreaViewUI = ({children}) => {
const [ height, setHeight ] = useState(0)
return (
<SafeAreaView
onLayout={() => {
if (Platform.OS === 'android') {
setHeight(StatusBar.currentHeight || 0);
}
}}
style={[styles.container, { paddingTop: height }]}>
<View style={styles.content}>
{ children }
</View>
</SafeAreaView>
);
If there's other possible answer. Kindly post it here.
Thanks!
I am trying to make the sliding image. I have followed the this . Its responding on sliding with fingers but not sliding automatically. How can I do so? I have implemented as follows:
<ViewPager style={styles.viewPager} initialPage={0}>
<View key="1">
<Image style={ {height: '100%', width:'100%'}}source={{uri :'https://images.unsplash.com/photo-1441742917377-57f78ee0e582?h=1024'}}></Image>
</View>
<View key="2">
<Image style={ {height: '100%', width:'100%'}}source={{uri :'https://images.unsplash.com/photo-1441716844725-09cedc13a4e7?h=1024'}}></Image>
</View>
</ViewPager>
By looking at the source code I have found there is a method setPage() which accepts page number as argument.
Look at the example code they have provided where you can find how to use reference and call setPage method Example
Now you can use setInterval() and make auto slide work.
setInterval(() => {
this.viewPager.current.setPage(page);
}, 1000);
Set page is a method to update the page of the viewpager. You can autoscroll the viewpager using a timer and by updating the pager by using the setPage method. Below is the complete code for the same.
import React, { Component } from 'react';
import { StyleSheet, View, Text, Platform } from 'react-native';
import ViewPager from '#react-native-community/viewpager';
export default class App extends Component {
state = {
pageNumber: 0,
totalPage: 2
}
componentDidMount() {
var pageNumber = 0;
setInterval(() => {
if (this.state.pageNumber >= 2) {
pageNumber = 0;
} else {
pageNumber = this.state.pageNumber;
pageNumber++;
}
console.log(pageNumber)
this.setState({ pageNumber: pageNumber })
this.viewPager.setPage(pageNumber)
}, 2000);
}
render() {
return (
<View style={{ flex: 1 }}>
<ViewPager style={styles.viewPager} initialPage={0}
ref={(viewPager) => { this.viewPager = viewPager }}
scrollEnabled={true}>
<View key="1">
<Text style={{ color: 'black' }}>First page</Text>
</View>
<View key="2">
<Text>Second page</Text>
</View>
<View key="3">
<Text>Third page</Text>
</View>
</ViewPager>
</View>
);
}
}
const styles = StyleSheet.create({
viewPager: {
flex: 1,
},
});
I bought this Theme which in Expo works flawlessly, but as soon as I build the APK, the Keyboard will cover the whole screen and wont work as supposed.
I'm using expo for testing and it works just fine.
return (
<SafeAreaView style={styles.container}>
<NavHeader title={thread.name} {...{navigation}} />
<FlatList
inverted
data={messages}
keyExtractor={message => `${message.date}`}
renderItem={({ item }) => (
<Msg message={item} name={item.me ? name : thread.name} picture={thread.picture} />
)}
/>
<KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"} enabled>
<View style={styles.footer}>
<TextInput
style={styles.input}
placeholder="Write a message"
value={this.state.message}
onChangeText={message => this.setState({ message })}
autoFocus
blurOnSubmit={false}
returnKeyType="send"
onSubmitEditing={this.send}
underlineColorAndroid="transparent"
/>
<TouchableOpacity primary transparent onPress={this.send}>
<Text style={styles.btnText}>Send</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
And the Styles
const styles = StyleSheet.create({
container: {
flex: 1
},
footer: {
borderColor: Theme.palette.lightGray,
borderTopWidth: 1,
paddingLeft: Theme.spacing.small,
paddingRight: Theme.spacing.small,
flexDirection: "row",
alignItems: "center"
},
input: {
height: Theme.typography.regular.lineHeight + (Theme.spacing.base * 2),
flex: 1
},
btnText: {
color: Theme.palette.primary
}
});
I have tried the following plugin
using the enableOnAndroid prop
https://github.com/APSL/react-native-keyboard-aware-scroll-view
with no success.
I have posted here:
https://github.com/APSL/react-native-keyboard-aware-scroll-view/issues/305
and here:
https://github.com/expo/expo/issues/2172
Unfortunately this is a known issue
https://github.com/expo/expo/issues/2172
Depending on the complexity of your screen layout you could add a bottom margin or padding using Keyboard listeners provided by React Native.
import React, { Component } from 'react';
import { Keyboard, TextInput } from 'react-native';
class Example extends Component {
componentDidMount () {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
}
componentWillUnmount () {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
_keyboardDidShow () {
this.setState({
marginBottom: 400
})
}
_keyboardDidHide () {
this.setState({
marginBottom: 0
})
}
render() {
return (
<TextInput
style={{marginBottom: this.state.marginBottom}}
onSubmitEditing={Keyboard.dismiss}
/>
);
}
}
I'm working on an app with a Side Menu and a Navigator. In the side menu there are menu-items which let's you navigate (using Navigator), and the menu-items also get styled to indicate which one is active.
When first going to a new route with navigator.push() and then going back with navigator.pop(), the menu-item corresponding to the previously active route (which is now inactive) does not get either of the styles to show that it is either inactive or active. The style of the menu item (RouteMenuItem in the full example below) is as follows
style={[
{ padding: 15, borderColor: 'firebrick', borderWidth: 1 },
(isActive
? {backgroundColor: 'green'}
: {opacity: 0.5}
)
]}
How is it possible that neither {backgroundColor: 'green'} nor {opacity: 0.5} gets applied?
The image below shows how the bug looks on Android: "Route ONE" is selected, however, the menu item for "Route TWO" does not have opacity: 0.5 as it should (it should be half transparent like the 3rd menu item).
Below is the full code for a minimal example to reproduce the bug. The component hierarchy is like this:
<Navigator renderScene={() => <SideMenu><View /></SideMenu>} />
PS: We use StyleSheet.create() in our code, but in the example below I've just defined the styles inline. It does not seem to make any difference.
import React from 'react';
import {View, Text, TouchableHighlight, Navigator, Dimensions} from 'react-native';
import SideMenu from 'react-native-side-menu';
/***************
/** Routes **/
/****************/
const ROUTES = {
ONE: () => ({ title: 'Route ONE' }),
TWO: () => ({ title: 'Route TWO' }),
THREE: () => ({ title: 'Route THREE' }),
};
/**************/
/** Main **/
/**************/
export default class Main extends React.Component {
render() {
return (
<Navigator
style={{flex: 1}}
initialRouteStack={[
ROUTES.ONE(),
]}
renderScene={(route, navigator) =>
<Scene route={route} navigator={navigator} />
}
/>
);
}
}
/***************/
/** Scene **/
/***************/
class Scene extends React.Component {
state = {
menuIsOpen: false,
}
openMenu = () => {
this.setState({ menuIsOpen: true });
}
onMenuOpenChanged = (menuIsOpen) => {
if (this.state.menuIsOpen !== menuIsOpen) {
this.setState({ menuIsOpen });
}
}
render() {
const {route, navigator} = this.props;
return (
<View style={{flex: 1}}>
<SideMenu
menu={
<Menu
route={route}
navigator={navigator}
/>
}
menuPosition="right"
bounceBackOnOverdraw={false}
onChange={this.onMenuOpenChanged}
isOpen={this.state.menuIsOpen}
openMenuOffset={Dimensions.get('window').width * 0.75}
disableGestures={false}
>
<Screen route={route} navigator={navigator} openMenu={this.openMenu} menuIsOpen={this.state.menuIsOpen} />
</SideMenu>
</View>
);
}
}
/**************/
/** Menu **/
/**************/
class Menu extends React.Component {
render() {
const {route, navigator} = this.props;
return (
<View style={{ flex: 1, backgroundColor: 'coral', paddingTop: 25 }}>
<Text>Currently at {route.title}</Text>
<RouteMenuItem forRoute={ROUTES.ONE()} route={route} navigator={navigator} />
<RouteMenuItem forRoute={ROUTES.TWO()} route={route} navigator={navigator} />
<RouteMenuItem forRoute={ROUTES.THREE()} route={route} navigator={navigator} />
</View>
);
}
}
const RouteMenuItem = ({forRoute, route, navigator}) => (
<TouchableHighlight onPress={() => navigator.push(forRoute)}>
<Text style={[ { padding: 15, borderColor: 'firebrick', borderWidth: 1 }, (forRoute.title === route.title ? {backgroundColor: 'green'} : {opacity: 0.5}) ]}>
Go to {forRoute.title} ({(forRoute.title === route.title ? 'current route' : 'NOT CURRENT ROUTE')})
</Text>
</TouchableHighlight>
);
/*****************************/
/** Screen, inside Menu **/
/*****************************/
class Screen extends React.Component {
render() {
const {route, navigator, openMenu, menuIsOpen} = this.props;
return (
<View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', backgroundColor: 'peachpuff', paddingTop: 25 }}>
<HeaderButton onPress={navigator.pop}>Back</HeaderButton>
<HeaderButton onPress={openMenu}>Menu</HeaderButton>
</View>
<View style={{ flex: 1, backgroundColor: 'white' }}>
<Text style={{ margin: 50, fontSize: 50 }}>
{route.title}
</Text>
</View>
</View>
);
}
}
const HeaderButton = ({onPress, children}) => (
<TouchableHighlight underlayColor="green" onPress={onPress}>
<Text style={{ padding: 10, borderColor: 'firebrick', borderWidth: 1 }}>
{children}
</Text>
</TouchableHighlight>
);
The problem occurs becauase children of TouchableHighlight gets default opacity (1) after the TouchableHighlight is pressed. As that is a more specific problem I've asked a new question here.
In this case the bug appears when going back to a previous route, because the menu item in that instance of the Menu was pressed (moving us to a new route before we could spot the bug).