Overlaying views in React Native - react-native

Im trying to make a dropdown similar to the image below and im wondering if such a thing is possible. That is because:
overflow defaults to hidden on android and that since zIndex doesnt work all that well.
zIndex doenst work all that well, views need to be in the proper order in order to draw over others normally
The only scenario that i can think of to make this work right now is to use something like onLayout and manually calculate the position of where it is that the dropdown needs to display and then render it at the top level in absolute positioning. I worry this might look rather hybrid-y but havent tried it yet.
Other ideas?

You can definitely use zIndex to achieve this behavior, but zIndex has to be applied to adjacent views to work cross platform:
render(){
return (
<View style={{ flex: 1, alignItems: 'flex-start' }}>
<View style={{ zIndex: 2 }}>
<YourDropdownButton />
</View>
<View style={{ zIndex: 1 }}>
<YourNormalButton />
</View>
</View>
)
}
Here is a snack showcasing this with my own custom drop down

Why wouldn't you use the native dropdown, it renders correctly and works as intended on all platforms?
Either way, you can always position it absolutely yes. I've done something like this and it works, but you can have some glitches if the list gets longer and it needs to scroll. Also, you would have to implement proper closing (clicking outside, and on the main element, closing after choosing the options. etc).

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 to set backgroundColor like gradient?

I just can set basic color which is static, doesnt change.
Also how can I do the borderRadius part, since i made two different View's.
On here, i just use this code for the color
<View style={{ paddingHorizontal: 20, backgroundColor: "#3DB4EE" }}>
Here is how my app looks:
And here is how i want it to be seen:
There's an easy way and a hard way:
Hard Way:
Use radial-gradient CSS property, here's an example: is it possible to do a curved line with css gradient?
Easy Way:
Get an Image designed with the same background and set as background-image
It's not possible without adding library and there for you have to use https://github.com/react-native-linear-gradient/react-native-linear-gradient
For border radius of white background you have to use style property borderTopLeftRadius and borderTopRightRadius

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.

ReactNative <Text> is shifting when changing content because of different alphabets, see gif

I am changing alphabets in a Text element but I get this slight shifting of elements. I have tried adding padding, margin and wrapping with other empty s but I keep getting this shifting as shown in the video. I've also used the various props options (need to only use the cross platform ones) but to no avail.
http://imgur.com/a/mNWGr
And my text is:
<Text style={{
fontSize: 24,
textAlign: 'center',
paddingTop: 5,
paddingBottom: 5}}>
Edit2: Correct answer (credits to Ajith Pandian) is that the height should have fixed value.
I think it's expected behaviour. If the app is iOS only you can try hard coding height and using adjustsFontSizeToFit to force the font to scale down.
Edit: This answer is posted with regards to RN 0.45.0 and older.

React Native justifyContent no effect

Figure, why setting the justifyContent property does not work?
When you are in a container that has the flex direction set to 'row' then justify-content actually sets the location horizontally instead of vertically. So in this case you would use alignItems. Since the RN implementation of flexbox is pretty close to the standard baring a few naming differences ('flexDirection' instead of 'flex-direction', etc) I would recommend working your way through the tutorial at http://flexboxfroggy.com/. Level 10 actually shows an example of the issue you are encountering here.
try to add alignItems: 'center'