I'm embedding YouTube videos in a React Native app and when that component mounts, YouTube opens a full screen video to play. That part is great. I want a full screen video.
The problem is that it puts it on top of every other single React Native component. I can't get any interaction feedback from the user. Even when I put a component at the top-most level with the highest z-index possible, the YouTube video still covers it.
I'd like the user to be able to swipe left or right to go to another video (I have the swiping part figured out, though it's not shown here). Is this even possible? How can I do this?
[Edit: Also, does anyone have any resources about how YouTube can put itself in front of all other components, including its iframe's parents?]
The code:
import React from 'react';
import { StyleSheet, Text, View, WebView } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View id={'webRoot'} style={styles.container}>
<WebView
ref={'webview'}
automaticallyAdjustContentInsets={false}
source={{uri: 'https://www.youtube.com/watch?v=43w7rcYPUnI'}}
javaScriptEnabled={true}
domStorageEnabled={true}
decelerationRate='normal'
startInLoadingState={true}
style={{zIndex: -1}} />
<Text style={{
position: 'absolute',
height: 300,
width: 300,
top: 0,
zIndex: 8999999999999999999
}}>
{"Won't be visible"}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Related
It's been 7 hours, I've read all the docs and similar SO questions, so any help would be appreciated.
My goal: have an app screen where the top 1/3 of the screen is made up of custom components (not the problem), and then the bottom 2/3 of the screen is a giant full-width super-long scrollable textfield for the user to enter several paragraphs (the problem)
The problem: Either the on-screen keyboard covers the text from the textfield, the textfield isn't scrollable, or when typing and you go off the bottom of the screen you aren't scrolled along with what you're typing - or a mix of all the 3.
Here is a rough image of what I desire:
Currently, my code looks like this:
export default function Post() {
const [text, setText] = useState("");
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<SafeAreaView >
<KeyboardAvoidingView enabled behavior='height' keyboardVerticalOffset={40} >
<View>
<TextInput scrollEnabled={true} placeholderTextColor={LIGHT} maxLength={300000} placeholder="enter text" multiline={true} onChangeText={(newVal) => setText(prev => {prev + newVal})} value={text}/>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
</TouchableWithoutFeedback>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: WHITE,
alignItems: 'center',
justifyContent: 'flex-center',
alignItems: "center",
marginHorizontal: 15,
// height: "100%",
},
textfield: {
textAlign: "left",
textAlignVertical: "top",
backgroundColor: "lavender",
height: "100%",
flex: 1,
},
scroll: {
// width: "100%"
}
});
Couple of issues with your approach and code in general.
textfield isn't scrollable
Placing anything scrollable inside a touchable is really weird and rarely behaves as you expect it, so avoid if possible, or if you really need it then pass a onStartShouldSetResponder={() => true} to your inner scroll view. But in your case, I suspect you don't actually want the keyboard to close if the user clicks inside the textInput, do you? He probably wants to add a word to a previous sentence or fix a type. Instead I suggest catching the touch outside of the textInput only, e.g. in your top third. Something like this (scrabble snack) should work:
import React, { useState } from 'react';
import { Text, View, StyleSheet, Touchable, TouchableWithoutFeedback, SafeAreaView, KeyboardAvoidingView, TextInput, Keyboard } from 'react-native';
export default function App() {
const [text, setText] = useState("");
return (
<KeyboardAvoidingView style={{flex: 1, marginTop: 45}} behavior="padding">
<View style={styles.upperContainer} onTouchStart={Keyboard.dismiss}>
<Text>My content in top third </Text>
</View>
<View style={styles.lowerContainer}>
<TextInput
scrollEnabled={true}
placeholderTextColor={"lightgrey"}
maxLength={300000}
placeholder="enter text"
multiline={true}
onChangeText={(newVal) => setText(prev => {prev + newVal})}
value={text}
/>
</View>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
upperContainer: {
flex: 1,
borderWidth: 2,
borderColor: "grey",
alignItems: "center",
justifyContent: "center"
},
lowerContainer: {
flex: 2,
borderColor: "black",
borderWidth: 2,
padding: 10
}
})
Notice how I pass flex 1 and 2 to the two child views to style them how you required it. The border is just added for better visibility.
i'm using react-native-mapbox-gl to show the map in my react app, on page load it should show the location of the user like how the google maps shows, but it fails to show instead it will show some other region of the map,
Can someone help?
Thanks in advance.
here is the snippet
import { StyleSheet, View } from "react-native";
import MapboxGL from "#react-native-mapbox-gl/maps";
MapboxGL.setAccessToken("<YOUR_ACCESSTOKEN>");
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
},
container: {
height: 300,
width: 300,
backgroundColor: "tomato"
},
map: {
flex: 1
}
});
export default class App extends Component {
componentDidMount() {
MapboxGL.setTelemetryEnabled(false);
}
render() {
return (
<View style={styles.page}>
<View style={styles.container}>
<MapboxGL.MapView style={styles.map} />
<MapboxGL.UserLocation />
</View>
</View>
);
}
}
You can pass children the MapboxGL.Mapview.
<MapboxGL.MapView style={styles.map}>
<MapboxGL.UserLocation/>
</MapboxGL.MapView>
Check this article that shows how to display user location marker using Marker component.
https://github.com/react-native-mapbox-gl/maps/issues/227
https://github.com/react-native-community/react-native-maps/blob/master/docs/marker.md
react-native mapbox is not showing user location and annotation
For me, it works(was showing the wrong location as of now):
<MapboxGL.MapView style={styles.map} zoomEnabled logoEnabled={false}>
<MapboxGL.UserLocation visible={true} />
</MapboxGL.MapView>
For more information you can refer to official docs.
https://github.com/nitaliano/react-native-mapbox-gl/blob/master/docs/MapView.md
https://github.com/rnmapbox/maps/blob/main/docs/UserLocation.md
P.S: MapboxGL.MapView has one props showUserLocation but it seems now working now,
I also tried several other props as mentioned in docs they are also not working, look docs are not updated!!
I'm building a React Native app, it uses React Navigation. I use TouchableOpacity throughout the app, however, in a stack navigator screen, it doesn't seem to work at all. Touching the element doesn't change the opacity and the onpress function doesn't work. The screen itself displays fine and all other screens in my app have TouchableOpacity's that work fine.
Using button doesn't respond either, I'm thinking this is a react navigation issue potentially? There is no issues transitioning to the screen though?
Here is my screen;
import React, {Component} from 'react';
import { View, Text, TouchableOpacity, Alert, Button} from 'react-native';
class RaceScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<View style={{ flex: 1, alignItems: 'center', backgroundColor:'rgba(30,30,30,0.98)'}}>
<TouchableOpacity onPress = {() => console.log('Hello')}>
<View style={{ margin:50, height:100, width: 200, backgroundColor:'red', alignItems:'center', justifyContent:'center' }}>
<Text style={{ color:'white' }}>
Go back
</Text>
</View>
</TouchableOpacity>
<Button title="Go back button" onPress = {() => console.log('Hello')}>
</Button>
</View>
);
}
}
export default RaceScreen
I've found that the Touchable components typically don't respond well to text children. You simply need to wrap it inside a View:
import React, {Component} from 'react';
import { View, Text, TouchableOpacity, Alert} from 'react-native';
export default class RaceScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', backgroundColor:'rgba(30,30,30,0.98)'}}>
<TouchableOpacity onPress = {() => console.log('Hello')}>
<View style={{ margin:50, height:100, width: 200, backgroundColor:'red', alignItems:'center', justifyContent:'center' }}>
<Text style={{ color:'white' }}>
Go back
</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
I finally figured it out. In the createStackNavigator method from react-navigation, transparentCard:true is a deprecated property and was causing the bug. I was using version 3 documentation on a version 4 package of react navigation.
Looking at there site, they have just released version 5 which is great!
A note to the less experienced developers like myself, making sure you're aware of the version of each package you are using is critical for some of these difficult bugs. Don't let it get you down though, react native is elite!
I have my own HeaderComponent with an image:
const CustomHeaderLogo = () => {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Image
source={require("../assets/logo.png")}
style={{ width: 160, height: 30 }}
/>
</View>
);
};
export default CustomHeaderLogo;
which I use in navigationOptions in stackNavigator on all my screens like this:
navigationOptions: {
headerTitle: () => <HeaderLogo />
}
It works but the problem is, that the image is flickering / blinking when navigating from screen to screen. That's especially noticeable on iOS.
Is there any way to prevent the image from flickering?
EDIT: Need to edit my question since I now know where the flickering is coming from.
It is the animation effect in the header. I still don't know how to disable it since animationEnabled setting to false doesn't change anything. https://reactnavigation.org/docs/4.x/stack-navigator#animationenabled
I am completing a tutorial on react native. For a certain screen, the instructor recommends the following code:
<Image source={bgImage} style={styles.backgroundContainer}>
<View style={styles.container}>
<Quote quoteText={this.props.text} quoteSource={this.props.source}/>
</View>
</Image>
But when I use this, I get the above error.
I've tried alternatives to this, but when I do, the background image doesn't even load.
EDIT: As requested below, here's my styling code. What I'm going for is using a background gradient image stored locally to the app code with text overlayed over that background. What I currently get by using the suggestion below is just the text at the very top of the screen and no background image.
const styles = StyleSheet.create({
backgroundContainer: {
flex: 1,
resizeMode: 'cover',
width: undefined,
height: undefined,
backgroundColor: '#889DAD',
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'transparent',
},
});
Since react-native 0.50 you can't nest components inside <Image> tag, rather you have to use <ImageBackground> for background images. Release Notes for v0.50.0
You are not allowed to put other components inside an image component. You need to wrap a View around your Image and positioned it as absolute.
<View style={{ flex: 1}}>
<Image source={bgImage} style={styles.backgroundContainer} />
<View style={styles.container}>
<Quote quoteText={this.props.text} quoteSource={this.props.source}/>
</View>
</View>
container: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
justifyContent: 'center',
alignItems: 'center',
},
EDIT:
Since react-native version 50.0, you can simply use ImageBackground
Use
<ImageBackground
source={image}
style={styles.contentContainer} >
// Your view content goes here
</ImageBackground>
const styles = StyleSheet.create({
contentContainer: {
flex: 1,
},
});
Works like a charm