React native navigation newbie: Fullscreen width on a showInAppNotification? - react-native

I'm using react-native-navigation to show error notification dropdowns via 'showInAppNotification'.
I've tried to style the dropdown box with:
{
backgroundColor: colorRed,
flex: 1,
alignSelf: 'stretch',
}
I can't get the box to obey that flex call. It stays as the width of the text inside the notification.
That is, what I get is this:
And what I want is this:
(The second is achieved by setting a hard width of 999, but that isn't a satisfactory solution)
So, from my limited understanding of React Native's stylesheet logic, I assumed I had a parent element with a fixed width above the notification. Except I don't. It's called directly (well, unless I'm missing some sort of injected showInAppNotification component) into my Provider HOC, which looks like this:
<Provider store={store}>
<ErrorBoundary>
{children}
</ErrorBoundary>
</Provider>
To confirm the ErrorBoundary was fullscreen width, I threw a backgroundColor: green on the error boundary. It came back as the expected width, like this:
Any thoughts on what could be going on? As mentioned I'm new to react native & it's possible I'm missing something obvious w/regards to flex logic, but I suspect it's a react-native-navigator notification issue I'm hoping others have run into. Any thoughts appreciated.

Instead of giving your width a hard-coded value you can import react native's Dimensions class into your component and use it in order to set the width.
So, your code can look something like this:
import { ...., Dimensions } from 'react-native';
const { width } = Dimensions.get('window');
const styles = {
notification : {
backgroundColor: colorRed,
width,
alignSelf: 'stretch'
}
}

Related

Set Header Height with Safe Area Insets with React Navigation

I can pass screenOptions to the Navigator with
a headerStyle object with a height property, but I'd like the height to take into account the SafeAreaInsets and not be a fixed value
There's getDefaultHeaderHeight function that takes into account the statusBarHeight here https://github.com/react-navigation/react-navigation/blob/dbe961ba5bb243e8da4d889c3c7dd6ed1de287c4/packages/drawer/src/views/Header.tsx#L8 - is there a way I can call this function and simply add n pixels across all devices?
I'm not sure about in React Navigation 5, but height is not a supported property of headerStyle in React Navigation 6. The rest of this response is based on references to and my personal experience with React Navigation 6.
You may need to write a fully custom header component to achieve what you want. React Navigation even has a Guide on supporting safe areas. Summarizing the Guide from React Navigation, plus a little extra real-world usage of it, you can then use the useSafeAreaInsets hook from react-native-safe-area-context and then in the style for the View surrounding your custom header, you can use the top value from the hook response as paddingTop to ensure that your header avoids the status bar area. If the rest of the height of your header needs to be explicitly defined, you'll need to add that top value to your height number as the height property of this View. If the height of your header is dynamic and based on its content, you probably don't actually need to set an explicit height on your header.
Example:
import React, { useEffect } from 'react';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const MyComponent = () => {
const insets = useSafeAreaInsets();
const navigation = useNavigation();
useEffect(() => {
navigation.setOptions({
// only us height if you REALLY need it, height should be dynamic based on content
header: () => <View style={{ paddingTop: insets.Top, height: value + insets.Top }}>
{content of your custom header}
</View>
});
}, [insets, navigation]);
};

React native form design

I want to create in form in react native which has material input text.
same like shown here https://material.angular.io/components/input/overview
Here is my code
import React, { Component } from "react";
import { Platform, StyleSheet, Text, View, TextInput } from "react-
native";
export default class App extends Component<Props> {
render() {
return <TextInput style={styles.abcd} placeholder="Enter name" />;
}
}
const styles = StyleSheet.create({
abcd: {
borderBottomWidth: 0.25,
marginVertical: 2,
paddingHorizontal: 10
}
});
Here, I have used a placeholder, but if you see the form in the given link, then it's not placeholder. Also, the text is moving in an upward direction, when we are clicking on the field. The same thing I want to achieve here.
I don't want to use any libraries like textField or any other library.
The placeholder prop on TextInput components has the place-holding text disappear upon the start of input. To achieve what you want to do, you can overlay a Text component over your TextInput component and map its style to a state variable. Upon focus, change the Text component's styling accordingly.
Buddy,
There are two things
1. React-Native material input box is only available in Android by default.
2. On iOS, (iPhone or iPad) you will see normal InputBox
To see the material input box on iOS devices, you have to do lots of coding. The best solution is to integrate third-party libraries like react-native-paper
Please refer a working example over here with react-native-paper library
https://github.com/callstack/react-native-paper/blob/master/example/src/TextInputExample.js

How to handle responsive layout in React Native

I'm using the react-native-dimension library for making my UI responsive as follows:
const{width,height} = Dimensions.get('window');
and in my style.js file :
imageBackgroundLandscape:{
width:height,
height:width
},
imageBackgroundPortrait:{
width:width,
height:height
}
The problem is that when I rotate the screen, the width and height variables have got previous values!
For example in the portrait mode my variables are:
width : 800
height: 1280
and when I rotate the screen my variables are:
width : 800 // previous value
height: 1280 // previous value
In addition, I use the react-native-orientation to determine the mode of the screen.
I want to know how can I change the values of them (width, height) automatically when I rotate the device, or are there any other libraries for this?
Thanks in advance.
I usually handle the height, width confusion with the following code:
//Dimensions.js
import {Dimensions} from 'react-native';
const {height, width} = Dimensions.get('window');
const actualDimensions = {
height: (height<width) ? width : height,
width: (width>height) ? height : width
};
export default actualDimensions;
Instead of requiring the height and width from Dimensions, use the actualDimensions and for managing the orientation gracefully you should give a try to this library as well.
The Dimensions are loaded before the JS bundle gets loaded into the app so it is recommended to fetch the height, width dynamically for every render
You can read this here
I usually used Flexbox to arrange the layout for my components. It helps them to be responsive. Maybe you could give a try too.
Layout with Flexbox
You can use these steps to make your UI responsive.
1: use percentage whenever it's possible
2: use the power of flexbox to make your UI grow and shrink
3: use Dimension API
Actually, you do right but half of the task. you got the width and height from Dimensions and it is right, but how react-native understand your orientation changes?
First, your code should understand the change of orientation, then you set a call-back function to change the state of your application for implementing new width and height.
Awfully, I don't know the react-native can understand a change of orientation with its built-in functions or not. So I'm using this library to understand orientation changes and then I use setState to re-render the codes.
Absolutely, I put the width and height inside state of the component.
If you wanna lock the orientation change, use this library.
Firstly:
You are facing that issue is because you forgot to call const{width,height}
= Dimensions.get('window'); again when the orientation has changed.
In order to get the latest value of width and height after the orientation change you would have to call the Dimensions.get('window') function again and get width and height from it's output.
Secondly:
Instead of using multiple libraries, you can just use one library(react-native-styleman), that lets you handle this type of stuff very easily:
Here is how the code would look like using react-native-styleman.
import { withStyles } from 'react-native-styleman';
const styles = () => ({
container: {
// your common styles here for container node.
flex: 1,
// lets write a media query to change background color automatically based on the device's orientation
'#media': [
{
orientation: 'landscape', // for landscape
styles: { // apply following styles
// these styles would be applied when the device is in landscape
// mode.
backgroundColor: 'green'
//.... more landscape related styles here...
}
},
{
orientation: 'portrait', // for portrait
styles: { // apply folllowing styles
// these styles would be applied when the device is in portrait
// mode.
backgroundColor: 'red'
//.... more protrait related styles here...
}
}
]
}
});
let MainComponent = ({ styles })=>(
<View style={styles.container}>
<Text> Hello World </Text>
</View>
);
// now, lets wire up things together.
MainComponent = withStyles(styles)(MainComponent);
export {
MainComponent
};
I am using react-native-responsive-screen. it is working also with orientation change
USAGE
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
listenOrientationChange as lor,
removeOrientationListener as rol
} from 'react-native-responsive-screen';
class Login extends Component {
componentDidMount() {
lor(this);
}
componentWillUnmount() {
rol();
}
render() {
const styles = StyleSheet.create({
container: { flex: 1 },
textWrapper: {
height: hp('70%'),
width: wp('80%')
},
myText: { fontSize: hp('5%') }
});
return (
<View style={styles.container}>
<View style={styles.textWrapper}>
<Text style={styles.myText}>Login</Text>
</View>
</View>
);
}
}
export default Login;

React Native - Using "flex" inside a FlatList

I'm starting to learn React Native, and I'm trying to create grid of 3 columns with images. I've been using the numColumns prop of the FlatList to specify 3 columns, and then setting flex:1 for my images so they should fill the space of the column. However flex:1 makes none of my images appear, while trying height:100,aspectRatio:1 shows all of my images in columns. Any idea why this is? My code is down below:
export default class ArtScrollView extends React.Component {
_renderItem = (item) =>
(
<Image style={styles.art} source={{uri:item.item.imgFilePath}}/>
)
render() {
return(
<FlatList numColumns={3}
data={Object.values(this.props.pods)}
renderItem={this._renderItem}/>
);
}
}
const styles = StyleSheet.create({
art:{
height:100,
aspectRatio:1,
//flex:1, <- Having this instead of specifying the height doesn't work
marginRight:10,
}
});
Auto-sizing images in ReactNative does not work. It just doesn't. You need to know the dimensions of images before you show them.
It is quite easy to use var {height, width} = Dimensions.get('window'); and use those as your reference for your images' sizing.
Use the inspector and see (and understand) what FlatList actually renders for you. You may understand why things do not work (not just in this case but generally)

React Native how to do min/max widths

I want to style a component in my interface. The component must have a width of at least 200, but I want to let it grow with screen width to up to 600. But, sometimes people use tablets or huge phones. And I don't want the component to be able to grow with the screen forever. I want it to have a maximum width of 600.
And I know maxWidth is a thing that is, at least for now, not a part of the flexbox implementation in React Native... so, is there a reasonable way to do this today?
You can use the maxWidth, maxHeight, minWidth, minHeight layout properties supported by React Native.
Document here React Native layout props.
Example:
StyleSheet.create({
container: {
maxWidth: '80%', // <-- Max width is 80%
minHeight: 20, // <-- Min height is 20
},
});
There is no such thing as "maxWidth" in React Native. You may want to style your component at run-time. Try playing with Dimensions. You can get screen width and screen height of the device and adjust width of your component accordingly.
You can define two different style objects.
For full-width component on a device having width less than 600.
componentStyle_1: {
flex: 1
}
For 600 width on a device having width greater than 600
componentStyle_2: {
width: 600
}
You can check the device width runtime.
var {height, width} = Dimensions.get('window');
if(width>600){
//load componentStyle_1
}
else{
//load componentStyle_2
}
Best way to get accurate results is to play with your code. Good luck!
Refer: https://facebook.github.io/react-native/docs/dimensions.html#content
Simple. Just use maxWidth in your styles.
In a practical manner, this is how you would use it:
import { StyleSheet, Text, View, Dimensions, (+ anything else you need such as Platform to target specific device widths } from "react-native";
// plus whatever other imports you need for your project...
In a class component, you would create a state called whatever, let's say deviceWidth. Then inside the component you would use:
constructor(props) {
super(props);
this.state = {
deviceWidth: 375, // Put in any default size here or just "null"
// plus any other state keys you need in your project
}
componentDidMount() {
const currentWidth = Dimensions.get("screen").width;
this.setState({deviceWidth: currentWidth});
}
In a functional component you would import:
import React, { useEffect, useState } from "react";
Then inside your functional component you would add in:
const [currentWidth, setCurrentWidth] = useState(null //or add in a default width);
useEffect(() => {
const currentWidth = Dimensions.get("screen").width;
setCurrentWidth({deviceWidth: currentWidth});
}, []);
You could also use:
const deviceDisplay = Dimensions.get("window");
const deviceHeight = deviceDisplay.height;
const deviceWidth = deviceDisplay.width;
..if you wanted to find the height as well. On Android, "window" gets you the full screen height including the upper bar while "screen" gets you height without upper bar. Window and screen on iOS are the same.
Then using inline styles so that you have access to the state, set the width & maxWidth:
<View style={[styles.wrapper, { width: this.state.deviceWidth, maxWidth: 400, // or whatever you want here. } ]} >
Any width settings in a wrapper style found in your StyleSheet object will be over-ridden by the inline style, just like in CSS.
Alternatively if you don't have any other styles declared in your StyleSheet object, just use:
<View style={{ width: this.state.deviceWidth, maxWidth: 400 }} >
Or in a functional component, that would be:
<View style={{ width: deviceWidth, maxWidth: 400 }} >