Is possible to achieve a "pixel perfect" positioning with React Native apps? - react-native

I have an app using Ionic Framework with dozens of custom images on top of each other (layered),
SVG text elements(with custom paths) and a few javascript plugins.
I thought of porting to React Native, but couldn't get a proper place to ask other than here..
Any React developer can give some directions, if a port is possible?

Yes, you can Port your Ionic Application to React Native with Pixel Perfect UI. For a specific Platform for IOS and Android, You can also write your code. You can start with React Native latest 0.61 React Native Documentation. And for Specific positioning for your SVG images, you can find several npm modules.
This is a great idea from moving your ionic App to React Native, It will give your App best performance as well as several npm packages are also available which makes its development fast and efficient.

for height width you can use below function for every child component
import {PixelRatio, Dimensions} from 'react-native';
let screenWidth = Dimensions.get('screen').width;
let screenHeight = Dimensions.get('screen').height;
export const DESIGN_HEIGHT_WIDTH = {HEIGHT: 736, WIDTH: 414};
/**
*
* #param {*} height height of the screen
*/
export const convertHeight = height => {
const elemHeight = typeof height === 'number' ? height : parseFloat(height);
return PixelRatio.roundToNearestPixel(
(screenHeight * elemHeight) / DESIGN_HEIGHT_WIDTH.HEIGHT,
);
};
/**
*
* #param {*} width width of the screen
*/
export const convertWidth = width => {
const elemWidth = typeof width === 'number' ? width : parseFloat(width);
return PixelRatio.roundToNearestPixel(
(screenWidth * elemWidth) / DESIGN_HEIGHT_WIDTH.WIDTH,
);
};

Related

How to get height of Header component in React Native Navigation

I have been searching for a good way to get the height of the Header component of a react-native stack navigator to no avail. I've come across a stale, complicated answer that doesn't provide the header height specifically, but seems to unavoidably combine the bottom tab bar height as well. I'd like to know how to calculate the height of just the navigation header and status bar with react-navigation.
For reference, my project is using react-navigation 3.11 however I would happily attempt an upgrade if there is a solution involving features exclusive to 4.x. I have checked the documentation and see how I could supply a static header style but I don't want this. I'd just like to be able to access the navigation header style's height attribute from within a view.
Thanks.
In React Navigation >4.x you can use HeaderHeightContext or useHeaderHeight with React's Context API to get the height of the header:
import { HeaderHeightContext } from '#react-navigation/stack';
// ...
<HeaderHeightContext.Consumer>
{headerHeight => (
/* ... */
)}
</HeaderHeightContext.Consumer>
or
import { useHeaderHeight } from '#react-navigation/stack';
// ...
const headerHeight = useHeaderHeight();

Which is the best approach make responsive layouts in react native

Which is the best approach make responsive layouts in react native
use react-native Dimension Api.
it provides features like :
1. set
2. get
3. addEventListener
4. removeEventListener
Add dimension event listener "change" in constructor.
everytime change listener is called check for Dimension.get('window').width/height
and set you CSS state accordingly.
to seperate iOs and android react-native provides "platform" api, using which we can load components for different device as well.
You can use flex for the style and you can also use this two functions based on iPhone 7's height and width.
Just use them when you need to set a responsive size somewhere.
const deviceWidth = () => Dimensions.get('window').width;
const deviceHeight = () => Dimensions.get('window').height;
function normalizeWidth(width) {
const ratio = width / 375;
return deviceWidth() * ratio;
}
function normalizeHeight(height) {
const ratio = height / 667;
return deviceHeight() * ratio;
}
I use react-native-responsive-layout which I find very easy to use.

React native dimensions for Google Pixel XL and 2 XL

I'm having trouble rendering a lottie animation in Google Pixel XL and 2 XL. But I don't have that device on hand, does anyone know the width and height in react native unit? or how do you do to detect this devices?
You can implement by importing Dimensions from react-native package itself as below
import { Dimensions } from 'react-native';
const window = Dimensions.get('window');
const screenHeight = window.height;
const screenWidth = window.width;
And use it appropriately inside any element
<View style={{height: screenHeight - 80}}>

Android Navigation Bar height React-Native

I'm trying to get the Android Bottom bar working (the bar where you have the back button) height with RN. I did the following:
Dimensions.get('window').height
I get the height with this bar! Since it can or cannot be there and can be bigger or larger depending on the settings, this is a big issue for me.
In iOS devices, screenHeight === windowHeight;
In Android devices with bottom navigator bar, screen height === windowHeight + statusBarHeight + bottomNavigatorBarHeight ;
In Android devices without bottom navigator bar, bottomNavigatorBarHeight is zero.
import {Dimensions, StatusBar} from 'react-native';
const SCREEN_HEIGHT = Dimensions.get('screen').height; // device height
const STATUS_BAR_HEIGHT = StatusBar.currentHeight || 24;
const WINDOW_HEIGHT = Dimensions.get('window').height;
I use sheet below to do that:
// RN version:0.57.0
let deviceH = Dimensions.get('screen').height;
// the value returned does not include the bottom navigation bar, I am not sure why yours does.
let windowH = Dimensions.get('window').height;
let bottomNavBarH = deviceH - windowH;
import { Dimensions , StatusBar } from 'react-native';
const screenHeight = Dimensions.get('screen').height;
const windowHeight = Dimensions.get('window').height;
const navbarHeight = screenHeight - windowHeight + StatusBar.currentHeight;
There is a new library which works like a charm
https://github.com/ConnectyCube/react-native-android-navbar-height
import { Dimensions } from "react-native";
import { getNavigationBarHeight } from "react-native-android-navbar-height";
// ...
const scale = Dimensions.get('screen').scale;
const navigationBarHeight = await getNavigationBarHeight();
const result = navigationBarHeight / scale;
first we need import
import { Dimensions , StatusBar } from 'react-native';
WindowHeight = Dimensions.get('window').height .
ScreenHeight = Dimensions.get('screen').height .
StatusBarHeight = StatusBar.currentHeight
WindowHeight = ScreenHeight - NavigationBarHeight
when we want to implement float button in the bottom of our page set WindowHeight for that's height and set bottom : StatusBar.currentHeight for child element .
when we don't have NavigationBar ,
WindowHeight = ScreenHeight
First as mentioned in other answers using react native Dimensions API in Android the window height= screen height - (status bar height + navigation bar height)
After few hours of investigations I found that in some Android devices Dimensions API gives a wrong window height number.
the solution for is using [react-native-extra-dimensions-android][1]
[1]: https://github.com/Sunhat/react-native-extra-dimensions-android it give you the following information:
REAL_WINDOW_HEIGHT - Actual height of screen including system decor elements
REAL_WINDOW_WIDTH - Actual width of screen including system decor elements
STATUS_BAR_HEIGHT - Height of the status bar
SOFT_MENU_BAR_HEIGHT - Height of the soft menu bar (supported on most new Android devices)
then you can calculate window height: REAL_WINDOW_HEIGHT -(STATUS_BAR_HEIGHT + SOFT_MENU_BAR_HEIGHT)
const navbarHeight = screenHeight - windowHeight + StatusBar.currentHeight;
In the landscape case, this is wrong and will get a negative number.
If you're referring to the status bar on top.
According to react native docs you can use
import { StatusBar } from 'react-native';
then in your code
StatusBar.currentHeight
UPDATE
You can get this using this module react-native-extra-dimensions-android
To detect if the soft android nav is present, you can use this module react-native-detect-navbar-android.

Screen width in React Native

How do I get screen width in React native?
I need it because I use some absolute components that overlap and their position on screen changes with different devices.
In React-Native we have an Option called Dimensions
Include Dimensions at the top var where you have include the Image,and Text and other components.
Then in your Stylesheets you can use as below,
ex: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
}
In this way you can get the device window and height.
Simply declare this code to get device width
let deviceWidth = Dimensions.get('window').width
Maybe it's obviously but, Dimensions is an react-native import
import { Dimensions } from 'react-native'
Dimensions will not work without that
April 10th 2020 Answer:
The suggested answer using Dimensions is now discouraged. See: https://reactnative.dev/docs/dimensions
The recommended approach is using the useWindowDimensions hook in React; https://reactnative.dev/docs/usewindowdimensions which uses a hook based API and will also update your value when the screen value changes (on screen rotation for example):
import {useWindowDimensions} from 'react-native';
const windowWidth = useWindowDimensions().width;
const windowHeight = useWindowDimensions().height;
Note: useWindowDimensions is only available from React Native 0.61.0: https://reactnative.dev/blog/2019/09/18/version-0.61
If you have a Style component that you can require from your Component, then you could have something like this at the top of the file:
const Dimensions = require('Dimensions');
const window = Dimensions.get('window');
And then you could provide fulscreen: {width: window.width, height: window.height}, in your Style component. Hope this helps
React Native Dimensions is only a partial answer to this question, I came here looking for the actual pixel size of the screen, and the Dimensions actually gives you density independent layout size.
You can use React Native Pixel Ratio to get the actual pixel size of the screen.
You need the import statement for both Dimenions and PixelRatio
import { Dimensions, PixelRatio } from 'react-native';
You can use object destructuring to create width and height globals or put it in stylesheets as others suggest, but beware this won't update on device reorientation.
const { width, height } = Dimensions.get('window');
From React Native Dimension Docs:
Note: Although dimensions are available immediately, they may change (e.g due to >device rotation) so any rendering logic or styles that depend on these constants >should try to call this function on every render, rather than caching the value >(for example, using inline styles rather than setting a value in a StyleSheet).
PixelRatio Docs link for those who are curious, but not much more there.
To actually get the screen size use:
PixelRatio.getPixelSizeForLayoutSize(width);
or if you don't want width and height to be globals you can use it anywhere like this
PixelRatio.getPixelSizeForLayoutSize(Dimensions.get('window').width);
React Native comes with "Dimensions" api which we need to import from 'react-native'
import { Dimensions } from 'react-native';
Then,
<Image source={pic} style={{width: Dimensions.get('window').width, height: Dimensions.get('window').height}}></Image>
Only two simple steps.
import { Dimensions } from 'react-native' at top of your file.
const { height } = Dimensions.get('window');
now the window screen height is stored in the height variable.
Just discovered react-native-responsive-screen repo here. Found it very handy.
react-native-responsive-screen is a small library that provides 2 simple methods so that React Native developers can code their UI elements fully responsive. No media queries needed.
It also provides an optional third method for screen orienation detection and automatic rerendering according to new dimensions.
First get Dimensions from react-native
import { Dimensions } from 'react-native';
then
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
in windowWidth you will find the width of the screen while in windowHeight you will find the height of the screen.
The latest method from 2020 is to use useWindowDimensions
the way i implemented it-
make a global.js file and set window width and height as global variables
const WindowDimensions= (()=>{
global.windowWidth = useWindowDimensions().width;
global.windowHeight = useWindowDimensions().height;
return (<></>);
})
in App.js file,import window dimensions and add it to return block
use width and height everywhere as global.windowHeight and global.windowWidth
using global variables is not a good design pattern. but this thing works
I think using react-native-responsive-dimensions might help you a little better on your case.
You can still get:
device-width by using and responsiveScreenWidth(100)
and
device-height by using and responsiveScreenHeight(100)
You also can more easily arrange the locations of your absolute components by setting margins and position values with proportioning it over 100% of the width and height
You can achieve this by creating a component and using it by importing it into the file you need.
import {Dimensions, PixelRatio} from "react-native";
const {width, height} = Dimensions.get("window");
const wp = (number) => {
let givenWidth = typeof number === "number" ? number : parseFloat(number);
return PixelRatio.roundToNearestPixel((width * givenWidth) / 100);
};
const hp = (number) => {
let givenHeight = typeof number === "number" ? number : parseFloat(number);
return PixelRatio.roundToNearestPixel((height * givenHeight) / 100);
};
export {wp, hp};
Now, you should use it.
import { hp, wp } from "../<YOUR PATH>";
buttonContainer: {
marginTop: hp("2%"),
height: hp("7%"),
justifyContent: "center",
alignSelf: "center",
width: wp("70%"),
backgroundColor: "#1C6AFD",
borderRadius: 5,
},
buttonText: {
fontSize: wp("3.5%"),
color: "#dddddd",
textAlign: "center",
fontFamily: "Spartan-Bold",
}
That way, you will make your design responsive. I suggest using simple pixels in the styling of circle things like avatar images, etc.
In other cases, the above code wraps components according to the density pixels of the screen.
If you have any better solution, please comment.
First, you must import Dimensions from 'react-native'
import { View, StyleSheet, Dimensions } from "react-native";
after that, you can save width and height in variables:
const windowsWidth = Dimensions.get('window').width
const windowsHeight = Dimensions.get('window').height
them you could use both as you need, i.e. in styles:
flexDirection: windowsWidth<400 ? 'column' : 'row',
Remember this, your object styles is outside your component, so the cariable declaration must be outside your component too. But if you need it inside your component, no problem, can use it:
<Text> Width: { windowsWidth }</Text>
<Text> Height: { windowsHeight }</Text>
you can get device width and height in React Native, by the following code:
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
docs: https://reactnative.dev/docs/dimensions
import {useWindowDimensions, Dimensions} from 'react-native'
let width1= useWindowDimensions().width // Hook can be called only inside functional component, tthis is dynamic
let width2=Dimensions.get("screen").width