React Native Flex Child Growth Seemingly Affected by Padding - react-native

I am experiencing some difficulty when using flex for layout in React Native. I have reduced the behaviour I am experiencing down the the following problem.
I have one container which fills the available space since it has flex set to 1. I then have a child within that container which should fill the container, so I have set it's flex to 1. I also want the container to have padding at the top. I would therefore expect the child to fill all of the parent apart from the top 20%. However, what I am seeing is that there is equal padding at the top and bottom of the container around the child (as if I had set paddingVertical instead of paddingTop).
Is anyone able to explain why this behaves as it does? I am also intrigued by the behavior I saw when creating a snack to illustrate this problem. On the iOS and Android simulators I am experiencing the behaviour which seems erroneous to me whereas the Web view seems to work as I would expect with only a gap at the top.
Thanks!
Snack example code
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<View style={styles.child}>
<Text>
Change code in the editor and watch it change on your phone! Save to get a shareable url.
</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'green',
paddingTop: '20%'
},
child: {
flex:1,
backgroundColor:'red'
},
});
Android - 'broken' behaviour
Web - 'expected' behaviour

Related

React Native text input is not responding to touch and not focusing when in multiple Modals

Our project requires us to use a modal that is inside another modal(I know it`s bad but it was not my decision :) ) and it seems like text inputs are unable to focus when they are inside nested modals?
Here is a super simple demonstration of a code that fails to focus on text input when placed inside nested modal.
import React, { useState } from "react";
import { Modal, StyleSheet, View, TextInput } from "react-native";
const App = () => {
const [text, setText] = useState('Some text');
return (
<View style={styles.centeredView}>
<Modal visible={true} transparent={true} >
<Modal visible={true} transparent={true} >
<TextInput value={text} onChangeText={setText} style={styles.textInput} />
</Modal>
</Modal>
</View>
);
};
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
textInput: {
width: 300,
height: 300,
backgroundColor: '#00ffff',
}
});
export default App;
Here is an expo demo of this code running
Is this something that is not supported at all or it`s possible to somehow force focus on the text input when clicked?
Okay, it seems like there's some sort of bug.
My best guess would be the following:
A modal will only allow you to focus on the components within that modal. Which makes sense, when using the Modal as a pop-up.
However, when you nest these Modal components, there is some issue figuring out whether the <TextInput> should be accessible or not.
Here's an adjusted version of yours: https://snack.expo.dev/qM68rALpM
Here, we can see that the <TextInput> does work within one <Modal>, but not within two. It won't work for 3 either.
So,
Our project requires us to use a modal that is inside another modal
Really? Does it require you to? Considering this is bugged behaviour - and it may not be a known one, stating that this solution is "required" is not something I would agree with. I suggest approaching this in a different way, as I suspect what has happened here is trying to solve X with Y, but Y isn't working and you want to solve Y.
If you want, you could elaborate on the problem (X) that you are trying to solve in the first place. It may be solved by having 2 <Modal>'s, but not nested, etc.
Ok, figured out what was going wrong.
I am not entirely sure what is causing this but if the two modals open at the same time, text input is unable to focus.
If however, the inner modal is shown after the first one was already open, it works just fine. Take a look at these two examples to see the difference in behaviour.
Modals open at the same time. Focus is not working
Second modal is opened with some delay(Even works without the delay as long as it opens a bit later than the first one)

React Native StyleSheet global.js variable style error

I'm not sure why, but my app does not like the StyleSheet I created for components. In index.js (top level) I import global var
import global from './src/global';
then I use global.width which is set to the width of the screen (correctly) in my styles.js file at /src/styles.js. I then export various styles from the Styles file like the one below called "button". Finally in my button component, I use the array notation for react native styles, giving several widths to the component (assuming the highest index takes precedence), but I just get an error.
Sample of exported "button" StyleSheet
...
padding: 12,
margin: 10,
//width: global.width/2.0,
alignSelf: "center",
marginTop: "auto",
...
Button Component
<TouchableOpacity
onPress={this.props.onPress}
style={[
button.regularContainer,
styles.localButtonStyle,
this.props.style,
]}>
<Text style={[
button.regularText,
styles.localTextStyle,
this.props.textStyle,
]}>
{this.props.title || 'Button'}
</Text>
</TouchableOpacity>
Error
Invariant Violation: [33,"RCTView",541,{"color":4278190080,"textAlign":"center","width":"<<NaN>>","backgroundColor":1308622847,"borderWidth":0,"borderColor":4294967295,"marginTop":40}] is not usable as a native method argument
These errors go away if I remove the width element from most of the three stylesheets interacting with the component: button.regularContainer, styles.localButtonStyle, this.props.style
global.js
import React from 'react';
import {
Dimensions,
Platform,
} from 'react-native';
let global: {
HermesInternal: null | {}
};
global.width = Dimensions.get('window').width
global.height = Dimensions.get('window').height
global.ios = Platform.OS === 'ios'
export default global;
The error looks like it's trying to assign an NaN (Not a number) value to width.
Is global.width/2.0 definitely producing a valid number?
I suggest replacing this division of a variable with an actual number and see if the error still occurs.

How to make possible to deselect text in a Text component in React Native?

I'm trying to make an app with React Native which shows a lot of information to the end user.
It's vital that the user can select/copy/paste the info from and to the app.
The selectable property of Text is quite useful since it uses the native android UI for selecting text.
My only problem is that if you select a part of the text (intentionally or accidentally), you can only deselect if you tap inside the Text component again.
That is, if I touch the screen anywhere else (where any other component would be, even its father), the text keeps being selected.
Take, for example, the "Hello World" in React Native Documentation, and just add the selectable property:
import React from 'react';
import { Text, View } from 'react-native';
export default function YourApp() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text selectable>
Try editing me! 🎉
</Text>
</View>
);
}
If you run it on android, you'll notice that you can indeed select and copy when you double tap (or long tap) as expected. But you won't be able to cancel the selection unless you tap on some part of the text again. If you touch any other part of the screen the selection UI won't go away.
Is there a way to achieve that? There are too many Text components in my app, with varying length and size. When users accidentally select something, a lot feel frustrated tapping away and nothing happening.
In this case I would use a TouchableWithoutFeedback component.
TouchableWithoutFeedback
Example from RN, where alert('Pressed!') is your function to remove selection.
function MyComponent(props) {
return (
<View {...props} style={{ flex: 1, backgroundColor: '#fff' }}>
<Text>My Component</Text>
</View>
);
}
<TouchableWithoutFeedback onPress={() => alert('Pressed!')}>
<MyComponent />
</TouchableWithoutFeedback>;

Why is my image (and child components) not showing with ImageBackground on React Native?

I am having an issue with the image just showing up on the application. Through search results, I mostly see the solution being that that the height and width was required and missing, but I have already implemented with no results.
I have looked at the routes multiple times and don't see any issues on that end.
Lastly, I thought it could be something to do with the image. I have altered the size and it worked with the <Image /> tag. However, I need it to be a background image.
Current Code
import React from 'react'
import { View, Text, StyleSheet, ImageBackground } from 'react-native';
import { MaterialCommunityIcons } from '#expo/vector-icons'
export default function TitleScreen () {
return (
<View>
<ImageBackground
source={require('../assets/images/title_background.png')}
style={styles.backgroundImage}
imageStyle={{resizeMode: 'cover'}}
>
<Text>testing</Text>
{/* <MaterialCommunityIcons
name={'cards-outline'}
size={100}
/> */}
</ImageBackground>
</View>
)
}
const styles = StyleSheet.create({
backgroundImage: {
flex: 1,
width: '100%',
height: '100%',
}
});
Folder Layout
assets
-- images
--- title_background.png
components
-- TitleScreen.js
Answered! The answer was to add flex: 1 to the parent view container - for those running into the same problem.

react native flatlist androidTV focus issue

Environment
react: 16.3.1
react-native: 0.55.3
Description
I've implemented a multi dimension list view on React Native with a few horizontal FlatLists . Everything displays correctly. However, when I move my focus all the way to the end of a row, the focus will automatically go to the row below when I try to go right (already at the end of the row).
Is there a solution to prevent this and make sure that focus will stop when it reaches the ends of a flatlist ?
Steps to Reproduce
Render a FlatList vertically with each row being another horizontal FlatList. Scroll to end of a row, try to move RIGHT and focus would go down to the next row.
Expected Behaviour
Expected Behaviour should be none since we're at the ends of the current row.
Actual Behaviour
Focus goes to the next row if at the backend of a row
Note
I've searched the docs and this is a specific issue to firetv/androidtv.
Same issue as issue #20100 but the bug is "closed".
Sample code
import React, {Component} from 'react';
import {View, Text, TouchableOpacity, ScrollView} from 'react-native';
export default class App extends Component {
render() {
const data = [];
for (let i = 0; i < 10; i++)
data.push(i);
return (
<View>
{[1, 2].map(() => (
<ScrollView horizontal style={{height: 210}}>
{data.map(i => (
<TouchableOpacity key={i}>
<View
style={{
backgroundColor: 'grey',
width: 200,
height: 200,
}}
>
<Text style={{fontSize: 60}}>{i}</Text>
</View>
</TouchableOpacity>
))}
</ScrollView>
))}
</View>
);
}
This is not really a (proper) solution, but more of a hack, but it does the job.. I found this out by pure coincidence; if you add a border to the ScrollView, you won't have this problem.. So you can maybe play around with this a bit (e.g. an invisible border).
Currently I have discovered this is not possible for tvOS or android or firetv. Unless I'm mistaken I am assuming there is a low number of people attempting to create connectedTv apps or if they are they have a very very simple interface
you should be able to handle this by setting the last item's nextFocusRight property to null or undefined.