react native flatlist androidTV focus issue - react-native

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.

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 ScrolView Giving warning for Flatlist

I am creating UI for my new project and the screen length is large so I put the Scrollview so that User can scroll the screen and on the same screen I am using SIX flautists to render some data but When I run my application on IOS simulator then I am getting warning on almost every screen where I am using Flatlist under Scrollview please check the attached screen shot
The warning appears because ScrollView and FlatList share the same logic, if FlatList run inside ScrollView, it's duplicated
By the way SafeAreaView doesn't work for me, the only way to solve is.you can use SafeArea like this
<SafeAreaView style={{flex: 1}}>
<FlatList
data={data}
ListHeaderComponent={ContentThatGoesAboveTheFlatList}
ListFooterComponent={ContentThatGoesBelowTheFlatList} />
</SafeAreaView>
This is happening because it isn't recommended to work with a FlatList within a ScrollView.
A workaround tho would be to add a property to your FlatList like so :
<FlatList
data={yourdata}
nestedScrollEnabled ----> Add this
/>
Hope it solves your problem
i get this case too and the best way is to disable that warning because sometimes we need to use flatlist inside scrollview
import React, { useEffect } from 'react';
import { LogBox } from 'react-native';
useEffect(() => {
LogBox.ignoreLogs(['VirtualizedLists should never be nested']);
}, [])

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>;

React Native Flex Child Growth Seemingly Affected by Padding

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

Child of TouchableHighlight loses opacity styling on press

When a child of a TouchableHighlight has an opacity, its opacity disappears (is set to 1) after the TouchableHighlight is pressed.
Running example here: https://rnplay.org/apps/c0NIjQ
Minimal example:
<TouchableHighlight onPress={() => {}}>
<Text style={{ opacity: 0.5 }}>
Press me!
</Text>
</TouchableHighlight>
Is there a way to mend this, or is it a bug in React Native?
TouchableOpacity works as I would have expected for TouchableHighlight (live code sample), so using TouchableOpacity could be a workaround. Note, however, that TouchableOpacity does not have an underlay which appears when active, so whatever you render underneath is what will "shine through" on press. Thus, it's not a perfect substitute for TouchableHighlight.
I'm not sure whether the behavior of TouchableHighlight is intended, some sort of a tradeoff or actually a bug, but looking at the code you can clearly see how it differs from TouchableOpacity in this regard:
TouchableHighlight always sets the child's opacity to 1 when it goes inactive.
TouchableOpacity sets the child's opacity to childStyles.opacity if it is set, otherwise 1, when it goes inactive.
You could work around it by implementing the onPressOut method of TouchableHighlight, and binding your opacity to a state property.
constructor (props) {
this.state = {opacity: 0.5}
}
render () {
return (
<TouchableHighlight
onPressOut={() => this.setState({opacity: 0.5})}
opacity={this.state.opacity}
>
....
</TouchableHighlight>
);
}
Not ideal I agree.