Android and React Native top navigation Bar - android

I would like to ask you about section selected on pictures below.
What is the name of this section and how I can style it in React Native? At now my APK have an ugly white bar and I can't see level of battery or WiFi.

The area with the battery and time is called the status bar. In most cases I've seen, the status bar is given a set height depending on the platform from ReactNative's Platform module.
Afterwards, you can pass this height to a <View> and add additional styling.
import { Platform, ... } from 'react-native'
...code...
const STATUS_BAR_HEIGHT = Platform.select({ ios: 20, android: 24 })
export default class MyComponent extends Component {
...code...
render() {
<View style={{ height: STATUS_BAR_HEIGHT, ...more styles here... }} />
<View>
...code...
</View>
}
}

Related

Expo (React Native): Statusbar is not showing on android and adds a padding top

When running the app with expo go, it's working fine on Android, but when I test it with the pre-release build, it remove the clock and adds a padding.
This is what I see when running on expo go and also what I want
Notice it show the Statusbar with the clock and notifications
Notice there's no space between the Statusbar and the image
This is what I get once I install the pre-release build
Notice it doesn't show the Statusbar
Notice the padding top that shouldn't be there
MainLayout
import React from 'react';
import {StyleSheet, SafeAreaView, View} from 'react-native';
import Constants from "expo-constants";
export default function MainLayout({children}) {
return (
<SafeAreaView style={[styles.screen]}>
<View
style={[styles.view]}
>
{children}
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
screen: {
paddingTop: Constants.statusBarHeight,
flex: 1,
},
view: {
flex: 1,
}
});
I think the padding top is caused by this line paddingTop: Constants.statusBarHeight but I assume it won't be an issue anymore once the StatusBar will be fixed.
Note 1: It's working as expected on iOS.
Note 2: I did see this component: https://docs.expo.dev/versions/latest/sdk/status-bar/
But based on my understanding, the default expo configuration should be what I expect (?) I tried anyway, but with no luck. I'm open to give a second chance.
I finally succeeded.
First I tried to add this to my app.config.js
"androidStatusBar": {
"backgroundColor": "#ffffff",
"barStyle": "dark-content",
"translucent": true,
"hidden": false
},
It did somehow worked, but the bar was grayed-out. When compiling I had a message that androidStatusBar.backgroundColor was conflicting with splash.backgroundColor
My assumption is that the splash screen change the status bar style when starting the application. So all I needed to do was to update the status bar once the app is started.
But now that I knew the configuration, I re-tried by removing the config above and re-adding expo-status-bar, but this time with the same configuration that what I had in androidStatusBar.
import React from 'react';
import {StyleSheet, SafeAreaView, View} from 'react-native';
import Constants from "expo-constants";
import {StatusBar} from "expo-status-bar";
export default function MainLayout({children}) {
return (
<SafeAreaView style={[styles.screen]}>
<View
style={[styles.view]}
>
{children}
</View>
<StatusBar style="dark"
translucent={true}
hidden={false}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
screen: {
paddingTop: Constants.statusBarHeight,
flex: 1,
},
view: {
flex: 1,
}
});
style: has to be dark because "dark" is for the content, not the bar.
translucent: has to be true. The doc says it's true by default, but I suppose the splash screen changed it to false.
hidden: Not sure if this is needed, but to this point, I prefer specified it.
As a final note: The reason the app was pushed down was specified in the translucent documentation
(boolean) - Sets android:windowTranslucentStatus in styles.xml. When false, the system status bar pushes the content of your app down (similar to position: relative). When true, the status bar floats above the content in your app (similar to position: absolute). Defaults to true to match the iOS status bar behavior (which can only float above content).

How to fix Empty Space on top of Curved Android Phone

My react-native app look totally fine on most Android devices (and iOS) I tested on emulator, but some devices with noticeable curved screen on top (Google Pixel 4, API 29), it shows a big empty region on top of the phone.
This does not look normal. Do you know how to fix it ?
I am using SafeAreaView but without any Android specific padding/margin.
<SafeAreaView style={{flex:1}}>
... My App Code come here.
</SafeAreaView>
I also tried to remove the the SafeAreaView and used regular View instead but it still wont go away.
Just for testing I removed everything and added a hello world test screen.
It still gives same wide empty space.
My App.js:
export default class Main extends React.Component {
constructor(props) {
super (props);
}
render () {
return (
<View style={{flex:1, backgroundColor: 'white'}}>
<Text> Hello World, How to fix this ? </Text>
</View>
);
}
}
AppRegistry.registerComponent(appName, () => Main);
You can't remove it, it's a display bug on the Pixel 4 emulator. A physical Pixel 4 doesn't have that gap.
See my other answer for a detailed explanation.
You can achieve this simply by hiding your StatusBar just like this:
import React from "react";
import { StatusBar, View, Text } from "react-native";
export default class Main extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
StatusBar.setHidden(true);
}
render() {
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<Text> Hello World, How to fix this ? </Text>
</View>
);
}
}
Update: set StatusBar's transluent attribute to true along with make its' background as transparent like this:
import React, { Component } from "react";
import { StatusBar, View, Text } from "react-native";
export default class Main extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
StatusBar.setTranslucent(true);
StatusBar.setBackgroundColor("transparent");
}
render() {
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<Text> Hello World, How to fix this ? </Text>
</View>
);
}
}
Have you tried using this way
<StatusBar translucent={true} hidden={true} /> {/* <--- Here */}
Check statusbar component where you can draw an app under the status bar by using the property named translucent. Reference link
I managed to fix this by going to AVD Manager -> Click on Wipe Data
Img

Can't use newly imported components in React Native?

I've been working on this program and I've recently tried to use some new components from the react-native library like Icon and Header but whenever I try to use them in the render function I get error:
"Invariant Violation: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports."
This is really weird to me because I was, and still am, using components like Image, Text, and View without a problem so I don't get why I would be having an issue now with these new components. I'm not sure what I changed in my program to cause something like this to happen.
Only thing I can think of is that "Settings" used to be a default class but it is now not, but that doesn't explain how the old component I was using from the library still work. Keep in mind the other components I imported before like Image and others still work.
Here's and snippet of the offending code:
import React, { Component } from 'react';
import {StyleSheet, Text, View, TouchableHighlight, Image, Header, Icon} from 'react-native';
import { createStackNavigator } from 'react-navigation';
export class Settings extends React.Component {
render(){
return (
<View>
<View style={{height: 55, backgroundColor: '#007ebc'}}>
<View style={{flexDirection: "row", marginLeft: 10}}>
<Icon //<-------USING ICON WILL GIVE ME ERROR
name = 'arrowleft'
/>
<Image source={require("../assets/LogoLrg.png")}
style={{ width: 55, height: 30, marginTop: 10 }}
/>
<Text style={styles.headerText}> Settings </Text>
</View>
</View>
</View>
)
}
I don't think Icon or Header component exists in react-native library.
You can check it in react native website or react-native.js source code.
http://facebook.github.io/react-native/docs/getting-started
Unless I have missed some major update to React Native, you cannot import Header and Icon components from react-native because they don't exist. These components may be a part of some open-source library like react-native-elements or native-base, so you first have to install them:
npm i native-base --save
or,
npm i react-native-elements --save
and then use them:
import { Header, Icon } from 'react-native-elements' //or 'native-base'
RN Elements: Icon, Header
Native Base: Icon, Header

Avoid status bar overlap on all screens

I want all screens on my app to appear below the status bar on both iOS and Android, so I'd either have to add a StatusBar component or a paddingTop to all my screens.
Is there a way to do this globally? Where is the appropriate top level component to add the StatusBar in a Redux app? (e.g. which part of https://github.com/react-community/react-navigation/tree/master/examples/ReduxExample)?
Step 1: Import Platform and StatusBar
import { Platform, StatusBar} from 'react-native';
Step 2: Add this style in parent View
paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0
Full Code:
import React, { Component } from 'react';
import {
Text, View,
Platform, StatusBar
} from 'react-native';
export default class App extends Component {
render() {
return (
<View style={{ paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }}>
<Text>This is Text</Text>
</View>
);
}
}
You can create a <NavigationContainer/> component to hold all your different pages, so that you don't need to duplicate the StatusBar and padding code in every single screen component.
I created a example in here: https://snack.expo.io/SyaCeMOwW
And nothing need to change in term of your navigation structure or redux flow.

Keyboard hides content for Android React Native webview

I am using React Native's <WebView> component.
The documentation has no mention of how to handle the keyboard hiding the webview when the webview's HTML contains an <input> which becomes focused on in Android.
Has anyone managed to solve this?
I have found a library that seems to work for regular <View>, but not a <WebView>.
you can wrap your WebView with a KeyboardAvoidingView
<KeyboardAvoidingView
behavior={Platform.select({ ios: "position", android: null })}
enabled
contentContainerStyle={{ flex: 1 }}
keyboardVerticalOffset={Platform.select({ ios: offset, android: 20 })}
style={{ flexGrow: 1 }}
>
<WebView/>
</KeyboardAvoidingView>
Have you thought about responding to system level events for the keyboard appearing and disappearing, then adjusting the WebView size appropriately?
There is an old question about how to handle this, it may or may not still be relevant. This answer in particular shows how to handle keyboard events. https://stackoverflow.com/a/33585501/1403
DeviceEventEmitter.addListener('keyboardDidShow',(frames)=>{
if (!frames.endCoordinates) return;
this.setState({keyboardSpace: frames.endCoordinates.height});
});
DeviceEventEmitter.addListener('keyboardWillHide',(frames)=>{
this.setState({keyboardSpace:0});
});
You could use the frames.endCoordinates.height value to alter the height of your WebView, ensuring that the content is not hidden behind the keyboard.
Just raising awareness that this can also be simply achieved by using react-native-keyboard-spacer if you are not in for intricate keyboard control.
import KeyboardSpacer from 'react-native-keyboard-spacer';
class DemoApp extends Component {
render() {
return (
<View>
<WebView ... />
<KeyboardSpacer/>
</View>
);
}
}
I used WebView.onTouchStart and ScrollView.scrollTo.
This is work like charm for me.
import { useRef } from "react";
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp
} from "react-native-responsive-screen";
const scrollRef = useRef();
const scrolldown = () => {
scrollRef.current.scrollTo((wp("100%") * 2) / 3);
};
<ScrollView ref={scrollRef} >
...
<WebView onTouchStart={scrolldown} >
...

Categories

Resources