Set WebView initial zoom level (start it so page fits) - react-native

I have a webview, and I set it's html like this:
<WebView source={{ html:body }} style={{ width:400; }} scalesPageToFit />
However on load, the page within is zoomed at 100% so its outside of the boundaries. Is it possible to start the zoom at a level so it fits perfectly inside the boundaries?
Here is a screenshot of what it looks like right now: https://i.imgur.com/i4nRnA0.png
I want it to start zoomed so all content fits like this: https://i.imgur.com/MtiyXMe.png (i manually pinched to zoom out here)
I thought the scalesPageToFit prop would do this, but its not doing anything, whether true or false. Does anyone know what scalesPageToFit does?
Thanks

scalesPageToFit avoids your web page to outscale in the webView, so that its minimum zoom does not show empty spaces.
Since React Native Docs version 0.52 a new prop initialScale is provided and seems to be exactly what you're looking for. Unfortunately it has never been added to the code: an issue is still open.
So, in order to achieve your objective, you have to use nativeConfig to override the native component behavior: what I mean is fully explained in these two examples:
First
Second

I have a similar WebView with a header and style={{flex : 1}} achieves this for me.

Related

What to do about diffrent screen sizes

I am learning react native for a few weeks and I made a screen and it looks good on my android emulator but when I look at it on my android phone somethings are out of place like icons or borders. I think It is about diffrent sizes of screens. Any idea how to fix this?
https://i.stack.imgur.com/rzhYn.jpg
https://i.stack.imgur.com/mhU2R.png
Yes, It could be.
You can avoid this in multiple ways.
Use dimensions, and get width and height based on the phone
https://reactnative.dev/docs/dimensions
or
https://www.npmjs.com/package/react-native-responsive-screen
For font size you can use this:
https://www.npmjs.com/package/react-native-responsive-fontsize
You have to make sure a few things while developing a component or when you style it:
Try to avoid fixed width/height or placement. Let the content grow the height of the box.
Either use flex or percentage width.
In your example, what I can see is the icon is going over the boundary of the box. To give a simple example, if you want to show a text on the left and say image on the right, use styles like this:
<View style={{display: 'flex', flexDirection: 'row', justifyContent:'space-between'}}>
<Text>Hi</Text>
<Image/>
</View>

How is the component view modified when keyboard is showing?

Good morning, this is actually my first question on StackOverflow after a few years in the industry (hope it's not too late!).
I'm working as a side project on a react native app.
I fail to understand how does the view change when the keyboard is up.
When the view shrinks (because the keyboard was shown), views overlap one to another. I want them to still be split.
I have this picture showing what I mean with overlapping views:
I thought it might be something with the paddings/margins, but I removed them all and still the same issue. Now, I know that the input height is defined by an absolute number, and that is what makes it not shrink, so it is bigger than the actual view, that's why it overlaps.
How can I keep my input having a fixed height but also maintaining a margin of separation when the view shrinks ??
Thank you very much!
Edit: I'm editing because I feel like I haven't been able to express my idea of how I need it to work. (Should I delete previous explanation? Keep picture if someone edits and deletes the first explanation).
The initial view with no keyboard has to be like this:
The inputs and buttons have to be at the bottom, the view getting all the height possible.
When opening the keyboard (by clicking on one of the inputs), I want the list to shrink so that the buttons and inputs are still visible and separated by a small margin/padding, and the list to have taken the remaining space (again respecting a small separation between views). The list will still be scrollable (it is a FlatList) when opening the keyboard.
Thank you again and sorry for the misexplanation.
You can try wrapping your content inside a ScrollView instead of a normal View like this:
<ScrollView style={{flex: 1}}>/* your content here */</ScrollView>
So when the keyboard shows up your elements won't overlap since they take the same space but you can scroll to see the elements hidden by the keyboard.
I think you can try something like this:
<View>
<ScrollView>
<KeyboardAvoidingView style={{flex:1}} behavior={Platform.select({ios:"padding", android:null })} keyboardVerticalOffset={Platform.select({ios: 0, android: 500})}>
{/*Your buttons and other elements here...*/}
</KeyboardAvoidingView>
</ScrollView>
<View>
You will also have to import KeyboardAvoidingView and ScrollView from react-native for this.

How do I get Detox to tap on nested text elements that have an onPress?

I seem to be having some issues with detox detecting nested elements.
I've created an inline link and need to click on it to have my tests progress.
Sample Code:
<Text>
This is the outer text
<Text
onPress={() => {}}
testID="clickable"
>
This is a clickable text component
</Text>
</Text>
How it looks:
This is the outer text This is a clickable text component
Failing test:
await expect(element(by.id('clickable'))).toBeVisible();
Now my issue is that the testID can not be detected and because of that clickable can not have .tap() appled to it.
I know that a possible solution is that we can wrap the nested text component in a view but that would require me to know exactly what the width and height are since an error is always displayed saying something like views nested within a <Text> must have a width and height. This is not possible since I have translations and the width and height might always be different.
I have also tried just straight up assigning the .tap() action to the outer text component but due to the length of the string, the action does not even come close to touching the testID.
Upon closer inspection of the native iOS elements using Xcode, it seems like the testID is not assigned to that particular section, and the whole component is just one giant string which could possibly explain why the testID could not be found.
Any help on this issue would be much appreciated. Thanks!
As you have already noted, the testID is not propagated through for the substring. So the testID won't appear in the view hierarchy and as a result Detox won't find it.
The first thought could be to wrap the text that you want to be tappable in TouchableOpacity (or similar) but that will just result in an invariant violation as the nesting of within is not currently supported by React-Native.
An alternative could be to use views to position your Texts, while removing the nested Texts so that the testID can be found in the view hierarchy. You could achieve a similar result to what you want by doing the following:
<View style={{flexDirection: 'row'}}>
<Text>This is the outer text </Text>
<Text onPress={() => {}} testID="clickable">
This is a clickable text component
</Text>
</View>
I've also solved this issue in certain cases by selecting the parent text instead and using methods like tapAtPoint() instead of tap():
// JSX
<Text testID="login">
<Text>Already have account?</Text>
<Text onPress={}>Login</Text>
</Text>
// Test
await element(by.id('login')).tapAtPoint({ x: 150, y: 50 });
It's more brittle than I'd normally like, but it does work ok for cases where you don't have the component that renders consistent bounds on different device screen sizes. Plus is that is allows you to use the "React-recommended" way to do text appearance or behaviour customization, so your JSX will look more consistent.

React-Native view was rendered with explicitly set width/height but with a 0 flexBasis

In React-native 0.39,
I often get this error but I don't really understand why (appart the fact that I didn't set flexGrow...).
Here is the error from the console
View was rendered with explicitly set width/height but with a 0 flexBasis. (This might be fixed by changing flex: to flexGrow:) View: <RCTShadowView: 0x6080005a02a0; viewName: RCTView; reactTag: 2608; frame: {{0, 0}, {nan, nan}}>
Can someone explain to me why this error is triggered ?
EDIT: The error comes from this bit of boilerplate code I added in on the main View :
flex: 1,
// remove width and height to override fixed static size
width: null,
height: null,
But If someone could shed a light on react-native styling or lead me to good resources, I'll be grateful :)
Refer to react-native/React/Views/RCTShadowView.m, there has comments
This works around a breaking change in css-layout where setting flexBasis needs to
be set explicitly, instead of relying on flex to propagate.
We check for it by seeing if a width/height is provided along with a flexBasis
of 0 and the width/height is laid out as 0.
The error is triggered when flex without defined flexBasis and having either width and height is zero.
Refer to react-native/Libraries/StyleSheet/LayoutPropTypes.js, we know the flexGrow, flexShrink and flexBasis receive values of number.
For visual guide, you might refer to this webpage, A Visual Guide to CSS3 Flexbox Properties.
Specifying flexDirection: 'row' solves the problem ¯\_(ツ)_/¯
As the error states - change the 'flex' to 'flexGrow' and the issue is solved.
The difficult part about this is how to locate which 'flex' needs to be changed from the whole project. What I did was (using Atom Editor, so 'Find in Project' ...) changing each 'flex:' with 'flexGrow:' (with the ':' at the end you make sure that you change a style) and then simply search the whole project again for a 'flexGrow' and change every 'flexGrow' from each file with 'flex' until you locate the corrupted 'flex'.
I prefer using flex instead of flexGrow, that's why I revert to flex. This is why: Layout Props
Hope this solves the issues.
In node_modules/react-native/React/Views/RCTShadowView.m add "//" at line 170 like this "// RCTAssert(!YGNodeIsDirty(node), #"Attempt to get layout metrics from dirtied Yoga node.");"

alignSelf: 'stretch' in iOS vs Android (aka width:100%)

I'm trying to style a component to stretch the whole width of the view. In Android this works by adding a style={{alignSelf: 'stretch', width: null}} in the component, however the same code on iOS does nothing. What would be a good workaround? Also any idea why they act differently?
I'm doing a button component that should work in various situations, so the idea is that the component itself should stretch (if the prop is given), instead of touching the container around it. So modifying the container's flex properties should be avoided, even though I could probably do it with something like justifyContent:stretch off the top of my head, but for this purpose let's rule this option out... Also because this is an app that is working now fine on Android and needs to be ported to iOS, so I'm trying to do as small changes as possible. I can't rewrite the entire code to work around this issues. I'd need a self-contained solution if possible...
Using RN 0.21. I know I should update but that's a headache that I'm saving for later...
Did you try add flex:1 to your component?
If your parent have any width and your only child flex: 1, then the child should have 100% width.