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.
Related
I am running the code posted (for Class Component) at:
https://reactnative.dev/docs/dimensions
Yet, at the Android Studio simulator, If I "rotate" the device the dimension's values do not change i.e. I was expecting that the height and width could change with the rotation but this is not happening. Any ideas why?
According to the info posted at the previous link it says:
Although dimensions are available immediately, they may change (e.g due to device rotation, foldable devices etc) 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).
I also tried using using useWindowDimensions but this is limited to functional react components.
So far, I can not find a reliable way to detect if an Android device rotated using React-Native and class components :-(
Note: This problem also happens with React Function Component
Try: https://reactnative.dev/docs/usewindowdimensions
It works for me
import { useWindowDimensions } from 'react-native';
const { height, width } = useWindowDimensions();
I had the same problem. Upgrading react-native to version 0.64.2 fixed it.
My problem on 0.61.5 was not that the values were not correct, but that the view was not re-rendered at all after the rotation, so I added this to the constructor() and it worked:
Dimensions.addEventListener('change', () => {
this.setState({});
});
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,
);
};
I’m currently using LayoutAnimation to animate a view when children are added. However, since LayoutAnimation causes everything to be animated, globally, and I can’t easily use built-in Animated library to fit my use-case, I’m wondering if react-native-reanimated is able to help.
Here's a snack of my current solution:
https://snack.expo.io/#insats/height-adapation
This is what the result of that looks like:
Is there a way to achieve the same thing without using LayoutAnimation? I've looked through all exampled in react-native-reanimated, and I've read through the docs but I'm still not sure if this is possible to do or how I should get started. I've thought about using Animated to move the item-wrapper out of the viewable area and "scroll" it upwards (using transform translateY) when items are added, but that would require fixed height, which I don't have.
I have 2 approaches that I can suggest out of my mind:
You can configure your LayoutAnimation only when your desired state changed. If you use hooks it would be too easy:
const [state,setState] = useState([]);
useEffect(()=>{
/*rest code*/
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
},[state])
Or if you use class component you can catch your desired state change in componentDidUpdate:
componentDidUpdate(prevProps,prevState){
if(prevState.items!==state.items){
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
}
}
You can use onLayout function of view:
addItem = () => {
this.setState({
items: [...this.state.items, {title:'An item',isNew:true}]
})
};
renderItems = () => {
return this.state.items.map((item, index) => {
let opacity = new Animated.Value(0);
return (
<Animated.View onLayout={({nativeEvent})=>{
if(this.state.item.isNew){
// here you got the height from nativeEvent.layout.height
// Then you have to store the height animate height and opacity to its precise value
// PS I used opacity:0 to calculate the height
}
}} key={index} style={[styles.item,{opacity}>
<Text>{item.title}</Text>
</View>
)
});
};
When it comes to react-native-reanimated I regard it as more faster version of react-native's Animated library. So either way you will have to calculate the height!
I'm using onLayout to detect screen orientation and it's working fine inside my root view, but when I implemented inside the drawer it didn't work, any reason why this happens ?
code :
import Drawer from 'react-native-drawer'
...
onLayout(e) {
console.log('onLayout');
}
<Drawer onLayout={this.onLayout}
It didn't log any thing when orientation changed!
This is because the Drawer component doesn't take onLayout as a prop. You can see in the source code that the rendered View does use onLayout, but it's not pulling from something like this.props.onLayout.
I'm not exactly sure what you're looking to do, but maybe this issue will help you. As it shows, you can pass a function into openDrawerOffset instead of an integer or a ratio in order to be a little more dynamic with how you set your offset:
openDrawerOffset={(viewport) => {
if (viewport.width < 400) {
return viewport.width * 0.1;
}
return viewport.width - 400;
}}
You might also benefit from the Event handlers that react-native-drawer has to offer.
React Native provides a view class called RCTRootView. You specify the frame in which the RootView should render things, and it goes ahead and does it.
In my use-case though, the size of the content view is dynamic, and depends on the data being passed into React Native. This size is important because I'm going to put the React Native view into e.g. a self-sizing cell.
How is this done?
#fatuhoku I came to the same conclusion after some digging around. For anyone else who's looking to do this, here's an example.
Declare your bridge to native code where we'll be sending the content
size (where depends on preference, I create the instance outside of
any class/function at the top of the file).
Call a method in the onLayout property of a JSX component.
In the onLayout method being called, send the content size data to the bridge.
Use the content size in the native ObjC or Swift code as you need.
// MyReactComponent.jsx (ES6)
// Modules
var React = require('react-native');
var { View } = React;
// Bridge
var ReactBridge = require('NativeModules').ReactBridge;
// Type Definitions
type LayoutEvent = {
nativeEvent: {
layout: {
x: number;
y: number;
width: number;
height: number;
};
};
};
// React Component
class MyReactComponent extends React.Component {
onViewLayout(e: LayoutEvent) {
ReactBridge.setLayout(e.nativeEvent.layout);
}
render() {
return (
<View onLayout={ this.onViewLayout }>
<ChildComponentExample />
</View>
);
}
}
Then in ObjC you use the RCT_EXPORT_METHOD as described in React Native's documentation to create the "ReactBridge" and handle the the data sent on the "setLayout" method. The data will be an NSDictionary in this case but you could just as easily send only the layout height and you'd then get a CGFloat.