React Native - Different image size between android & iOS - react-native

I use the same code for android & iOS. However, I found the appearances are different between two platforms, especially the image size (shown as below).
I wanna ask:
How can I set a configuration to make two platforms become consistent?
How to set android & iOS stylesheet setting on the same code?
Thanks!!
<MenuButton onPress={() => this.toggle()} style={styles.menuButton}>
<Image source={require('../images/menu.png')} style={styles.menuButtonImage}/>
</MenuButton>
StyleSheet setting
Android & iOS output

I also noticed images get rendered differently on the other platform. If I remember correctly it should be enough to set a static size. If you have to tweak the style for each platform I would do the following:
# Use a ternary statement in the function that gets your style object:
getImage () {
const getStyle = () => ({height:(Platform.OS === 'ios' ? 36 : 48)})
# then call it where you set the propery:
return <Image source={require('../images/menu.png')} style={getStyle()} />
}
This way it will get called on each re-render of the parent.
In fact, I have all styles defined like this. It works like a charm for dynamic styles that may be dependent on properties. Also, it's a nice pattern to keep components and functions in components that return elements as self contained as possible.

Related

React Native Dimensions not working on rotation

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({});
});

Setting image require path dynmanically

In react native navigation I use a custom icon, I want to be able to change this icon depending on if the user is in dark mode or normal mode.
The challenge I'm having is passing in the value of the path dynamically. I want to call a method inline that returns the file name of the icon.
<Marker
coordinate={this.state.region}
image={require("./" + {chkDarkMode()} + ".png")}
/>
How can I dynamically set the image? I've seen the conditional if length is equal to zero, but that example doesn't allow for multiple possible images.
Unfortunately, that's not allowed.
You can instead call require conditionally:
const image = darkMode ? require("./darkModeImage.png") : require("./lightModeImage.png")
One way to do this:
getImagePath = () => {
return `./${chkDarkMode()}.png`
}
<Marker
coordinate={this.state.region}
image={getImagePath()}
/>

ScrollToLocation not working on initial mount

I'd like to add a SectionList to my app such that it renders to a specific section (that isn't the first section in the list). Calling scrollToLocation on componentDidMount does not work; however, adding a button that calls scrollToLocation does. Is there a reason for this?
Could this be due to the SectionList reference (I've tried a few approaches for assigning reference, e.g. variable assignment, function assignment, using createRef, etc.)?
Here is a link to a stripped-down Expo snack to illustrate what I mean: https://snack.expo.io/#bobbymoogs/scrolltolocation-on-componentdidmount.
I found the best solution on this thread is to use onLayout to trigger the scroll:
scrollToInitialPosition = () => {
this.scrollViewRef.scrollTo({ y: 100 });
}
...
<ScrollView
ref={(ref) => { this.scrollViewRef = ref; }}
onLayout={this.scrollToInitialPosition}
/>
Note there are lots of other suggestions using setTimeout, componentDidUpdate, InteractionManager, etc. However using onLayout was the only one that worked for me (and also seems to me to be the cleanest).

loop and get all TextInput value in a component/screen

I know that the practice of react native is to use onChangeText for change value as follow.
<TextInput
onChangeText = {(text)=> this.setState({myText: text})}
value = {this.state.myText}
/>
However, I wonder if i could do something like this. To summarise, I want to loop through all the TextInput and get the ref and value. I just want to do things in javascript way as follow. Is that possible to be done?
<TextInput id="id1" ref={ref => (this.remark = ref)} />
<TextInput id="id2" ref={ref => (this.remark1 = ref)} />
onSubmit = () => {
forEach(TextInput in component) {
console.log(TextInput.id) <- note id is custom property
console.log(TextInput.refName)
console.log(TextInput.value)
}
}
Yes, but I wouldn't recommend this approach. You could simply create an array of refs and loop through it in your onSubmit function.
forEach(TextInput in component) {
This is not possible in any javascript environment (not only because forEach and for..in syntax is different but also you can't expect to be able to loop over component elements by type (?) and get them)
What you want to do is not javascript way but old style browser way:
there are no ids in react-native
technically you could get uncontrolled TextInput's value like you would do in plain react in browser environment (via this.textInputRef._lastNativeText) but it's discouraged in react-native, most likely because because instead of DOM react native has to render to native views which all differ depending on the platform (iOS, Android, Windows, etc) but have to work the same
So it's not only impossible in react native but in plain react as well. It looks to me like you want to create a form, and sooner or later you will find out that you want validation or transformation on your inputs and switch back to controlled components anyway

Using CSS filters in react-native

It seems that react-native doesn't implement CSS' filter property.
Is there a way to replicate those? Specifically I am looking for a way to change the following to an image, without creating a special image just for that:
Brightness
Hue
Saturation
Blur
Blur for images is already supported by RN via blurRadius prop. The remaining filters you can find in my react-native-color-matrix-image-filters library:
import { Image } from 'react-native';
import { Saturate } from 'react-native-color-matrix-image-filters';
const SaturatedImage = ({ saturate, ...imageProps }) => (
<Saturate value={saturate}>
<Image {...imageProps} />
</Saturate>
);
Update RN 0.62.2:
I was using above mentioned Library react-native-color-matrix-image-filters, but I was looking for web support too. As of right now React Native for web supports the css filter property: https://github.com/ndbroadbent/react-native-web/blob/91e4528eac16e10fd3d42644fc4c0c8047bee1bd/docs/components/View.md
For iOS and Android this style property does not work.