Related
On Android elements wrapped in BlurVIew don't positioning right.
It works on iOS devices fine. But on Android, elements wrapped in <BlurView>{children}</BlurView> run into each other. Screenshot is below
Sometimes when I change something in styles in dev mode, it works correctly, but when I build apk, bug appears again.
How can I fix it on Android?
Code
const BottomNavigationTabs: React.FC<BottomTabBarProps> = ({
descriptors,
state,
navigation,
}) => {
const focusedOptions = descriptors[state.routes[state.index].key].options;
return (
<>
<BlurView blurType="light"
blurAmount={15} style={{ height: 85, width: '100%', position: 'absolute', bottom: 0, }}>
<View style={{ display: 'flex', flexDirection: 'row', position: 'absolute', bottom: 0, justifyContent: 'space-between' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const focusedColor = isFocused ? colors.text1 : colorsOld.black;
//Weird snippet, to render passed icon just call function with any return value, then just set color
const icon =
options.tabBarIcon &&
React.cloneElement(
//#ts-ignore
options.tabBarIcon((props: any) => props),
{ color: focusedColor }
);
const onPress = () => {
const event = navigation.emit({
type: "tabPress",
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: "tabLongPress",
target: route.key,
});
};
const tabBtn = (
<TouchableOpacity
accessibilityRole="button"
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
style={styles.tabButton}
onLongPress={onLongPress}
activeOpacity={0.7}
key={route.key}
>
<View style={styles.tabItem}>
<View style={styles.tabItemIcon}>{icon}</View>
<Text style={{ ...styles.tabItemLabel, color: focusedColor }}>
{label}
</Text>
</View>
</TouchableOpacity>
);
return tabBtn;
})}
</View>
</BlurView>
</>
);
};
const styles = StyleSheet.create({
container: {
alignItems: "center",
justifyContent: "center",
paddingTop: 9,
paddingBottom: 15,
},
tabButton: {
paddingTop: 8,
paddingBottom: 15,
paddingHorizontal: 10,
borderRadius: 10,
zIndex: 10000
},
tabsContainer: {
backgroundColor: colors.secondaryBg(0.5),
width: "100%",
left: 0,
bottom: 0,
zIndex: 999,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-around",
},
tabItem: {
justifyContent: "center",
alignItems: "center",
},
tabItemIcon: {
marginBottom: 6,
},
tabItemLabel: {
fontSize: 12,
fontFamily: "Inter-Medium",
},
});
Found a solution here https://github.com/Kureev/react-native-blur/issues/483#issuecomment-1199210714.
Solution is to not set to <BlurView> position: absolute and to not wrapping anything with it. In my case looks like:
import React from "react";
import {
Text,
View,
ImageBackground,
TouchableOpacity,
StyleSheet,
} from "react-native";
import { BlurView } from "#react-native-community/blur";
import { BottomTabBarProps } from "#react-navigation/bottom-tabs";
import colorsOld from "src/theme/colorsOld";
import colors from "src/theme/colors";
const BottomNavigationTabs: React.FC<BottomTabBarProps> = ({
descriptors,
state,
navigation,
}) => {
const focusedOptions = descriptors[state.routes[state.index].key].options;
return (
<View
style={{
display: "flex",
flexDirection: "row",
backgroundColor: colors.secondaryBg(0.5),
position: "absolute",
bottom: 0,
justifyContent: "space-between",
}}
>
<BlurView
blurType="light"
blurAmount={15}
style={{ height: 85, width: "100%", bottom: 0 }}
/>
<View style={styles.tabsContainer}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const focusedColor = isFocused ? colors.text1 : colorsOld.black;
//Weird snippet, to render passed icon just call function with any return value, then just set color
const icon =
options.tabBarIcon &&
React.cloneElement(
//#ts-ignore
options.tabBarIcon((props: any) => props),
{ color: focusedColor }
);
const onPress = () => {
const event = navigation.emit({
type: "tabPress",
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: "tabLongPress",
target: route.key,
});
};
const tabBtn = (
<TouchableOpacity
accessibilityRole="button"
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
style={styles.tabButton}
onLongPress={onLongPress}
activeOpacity={0.7}
key={route.key}
>
<View style={styles.tabItem}>
<View style={styles.tabItemIcon}>{icon}</View>
<Text style={{ ...styles.tabItemLabel, color: focusedColor }}>
{label}
</Text>
</View>
</TouchableOpacity>
);
return tabBtn;
})}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: "center",
justifyContent: "center",
paddingTop: 9,
paddingBottom: 15,
},
tabButton: {
paddingTop: 8,
paddingBottom: 15,
paddingHorizontal: 10,
borderRadius: 10,
zIndex: 10000,
},
tabsContainer: {
width: "100%",
left: 0,
bottom: 0,
zIndex: 999,
position: 'absolute',
flexDirection: "row",
alignItems: "center",
justifyContent: "space-around",
},
tabItem: {
justifyContent: "center",
alignItems: "center",
},
tabItemIcon: {
marginBottom: 6,
},
tabItemLabel: {
fontSize: 12,
fontFamily: "Inter-Medium",
},
});
export default BottomNavigationTabs;
I'm quite new to React Native and React in general, and I'm stuck on this particular problem:
I followed some tutorials and other answers on other posts there on StackOverflow, but I can't manage to see the border Shadow I set on these "cards". The shadow isn't displayed on my phone.
I hope so of you old wizards of the internet can help me find a solution to this problem, I'd be really grateful.
export class Boss extends Component<IProps, IState> {
constructor(props: any) {
super(props);
this.state = {
hp: props.hp,
ap: props.ap,
};
}
render(){
return(
<View style={styles.cardContainer}>
<View style={[styles.cardBackground , this.state.hp > 0 ?
{ backgroundColor: 'gold' }
: { backgroundColor: 'red' }]}>
<View style={styles.cardFrame}>
<Text style={styles.cardName}>{this.props.name}</Text>
<View style={styles.bossLifeWrapper}>
<Button title={'+'} onPress={this.incrementeHP}></Button>
<Text style={styles.bossHP}>{this.state.hp}</Text>
<Button title={'-'} onPress={this.decrementeHP}></Button>
</View>
<Text style={styles.bossAP}>{this.state.ap}</Text>
<Text style={styles.bossPowerLabel}>{this.props.passive}</Text>
<View style={styles.cardTextBox}>
<Text style={styles.bossPowerLabel}>Pouvoir: {this.props.powerLabel}</Text>
<Text style={styles.bossEnrageLabel}>Enrage: {this.props.enrageLabel}</Text>
</View>
</View>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
cardContainer: {
width: '80%',
height: 450,
backgroundColor: "#171314",
alignItems:"center",
borderStyle: "solid",
borderColor: "black",
borderWidth: 1,
margin: '10%',
borderRadius: 10,
padding: 10,
shadowColor: "white",
shadowOffset: {
width: 0,
height: 8,
},
shadowOpacity: 0.44,
shadowRadius: 10.32,
elevation: 16,
},
cardBackground: {
backgroundColor: '#171314',
borderRadius: 5,
padding: 10,
zIndex: 0
},
cardFrame: {
zIndex: 1,
position: 'relative',
height: '98%',
maxWidth: '97%',
left: '1%',
top: '0.5%',
display: 'flex',
flexDirection: 'column',
backgroundColor: 'white'
},
cardName: {
flex: 1,
backgroundColor: 'red',
alignItems:"center",
borderStyle: "solid",
borderBottomColor: "grey",
borderBottomWidth: 5,
margin: 5,
marginHorizontal: 5,
fontSize: 20,
height: 10
},
bossHP: {
width: '100%',
color: 'blue'
},
bossAP: {
width: '100%',
color: 'red'
},
bossLifeWrapper: {
flex: 1,
flexDirection: "column"
},
});
have you tried elevate in box styles? ex: elevate:10,
I am a newbie to react-native. I am currently trying to implement the code which can scan and capture image for an ID card. Basically i am able to take image and save to gallery by using react native camera, but i have no idea how to detect the ID card border. I am seeking help which can guide me about the card border detection or some open source library that can implement such function.
Basically, I have already tried to implement react-native-documentscanner-android and rn-doc-scanner-android library. But react-native-documentscanner-android library i failed to implement and the rn-doc-scanner-android is without card border detection function.
Here is my code:
import React, {Component} from 'react';
import { RNCamera } from 'react-native-camera';
import {
StyleSheet,
View,
Text,
TouchableOpacity,
ToastAndroid
} from 'react-native';
import {
Colors
} from 'react-native/Libraries/NewAppScreen';
import Dimensions from 'Dimensions';
import CameraRoll from "#react-native-community/cameraroll";
export default class App extends Component {
constructor(props){
super(props)
}
state = {
barcodes: [],
}
render(){
const { height, width } = Dimensions.get('window');
const maskRowHeight = Math.round((height - 500) / 20);
const maskColWidth = (width - 300) / 2;
return (
<View style={styles.container}>
<RNCamera
ref={ref => {
this.camera = ref;
}}
style={{
flex: 1,
width: '100%',
justifyContent: "center"
}}
>
<View style={styles.maskOutter}>
<View style={[{ flex: maskRowHeight }, styles.maskRow, styles.maskFrame]} />
<View style={[{ flex: 30 }, styles.maskCenter]}>
<View style={[{ width: maskColWidth }, styles.maskFrame]} />
<View style={styles.maskInner} />
<View style={[{ width: maskColWidth }, styles.maskFrame]} />
</View>
<View style={[{ flex: maskRowHeight }, styles.maskRow, styles.maskFrame]} />
</View>
</RNCamera>
<View style={{ flex: 0, flexDirection: 'row', justifyContent: 'center', backgroundColor: '#2E8B57', margin: 5}}>
<TouchableOpacity onPress={this.takePicture.bind(this)} style={styles.capture}>
<Text style={{ fontSize: 14 }}> SNAP </Text>
</TouchableOpacity>
</View>
</View>
);
}
takePicture = async() => {
if (this.camera) {
const options = { quality: 0.5, base64: true };
const data = await this.camera.takePictureAsync(options);
console.log(data.uri);
ToastAndroid.show(data.uri, ToastAndroid.LONG);
if(data.uri!= null){
console.log('not null')
}else{
console.log('null')
}
CameraRoll.saveToCameraRoll(data.uri);
}
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#2E8B57",
overflow: 'hidden',
//width: 350,
//height: 150,
},
camera: {
flex: 1,
alignItems: "center",
justifyContent: "center"
},
scrollView: {
backgroundColor: Colors.lighter,
},
engine: {
right: 0,
},
body: {
backgroundColor: Colors.white,
},
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
color: Colors.black,
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
color: Colors.dark,
},
highlight: {
fontWeight: '700',
},
footer: {
color: Colors.dark,
fontSize: 12,
fontWeight: '600',
padding: 4,
paddingRight: 12,
textAlign: 'right',
},
maskOutter: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'space-around',
},
maskInner: {
width: 300,
//height: 300,
backgroundColor: 'transparent',
borderColor: '#DC143C',
borderWidth: 1,
},
maskFrame: {
backgroundColor: 'rgba(1,1,1,0.6)',
},
maskRow: {
width: '100%',
},
maskCenter: { flexDirection: 'row' },
});
I am creating an application for android and ios in react-native(0.57.7) and using react-native-video to play videos uploaded into vimeo. After integrate react video plugin, tested in both device. In ios it works perfectly but in android, I am not able to play video in full-screen mode. Here is my code for Android:
import React, { PureComponent } from 'react';
import {
View,
Text,
Image,
ImageBackground,
StyleSheet,
SafeAreaView,
TouchableOpacity,
ActivityIndicator
} from 'react-native';
import PropTypes from 'prop-types'
import Video from "react-native-video";
import Orientation from 'react-native-orientation-locker';
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from '../components/Resposive';
import RF from "react-native-responsive-fontsize"
export default class Videoplayer extends PureComponent {
constructor(props){
super(props);
this.state = {
loading: true,
videoFileArr:[],
showPlayer:false,
playing:false
}
}
componentDidMount() {
Orientation.lockToLandscape();
this.fetchVimeoVideo();
}
componentWillUnmount() {
Orientation.lockToPortrait();
}
goToHome(){
Orientation.lockToPortrait();
this.props.navigation.goBack();
}
fetchVimeoVideo = async () => {
await this.setState({ loading: true });
const { navigation } = this.props;
const jsonReceived = navigation.getParam('item', {})
const url = "https://api.vimeo.com/me/videos/" + jsonReceived.video_link
console.log(url)
const response = await fetch(
url, {
method: "get",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization:"Bearer f9e937d64037e657addcf088f28e6cb5"
}
});
const jsonResponse = await response.json();
const { files} = jsonResponse;
if (response.status != 200) {
alert(response.status)
}
console.log(files)
await this.setState({ videoFileArr:files, loading: false });
};
renderOptions = () => {
if (this.state.loading === true) {
return (
<View style={{
flex: 1,
alignItems: "center",
justifyContent: "center"
}}>
<ActivityIndicator size="large" color="#00ff00" />
<Text style={{ fontFamily: "Futura Std", fontSize: RF(3.0), fontWeight: "900", color: "#244E25", textAlign: "center" }}>Please wait while we are loading questions for you</Text>
</View>
)
}else if (this.state.videoFileArr.length> 0 && this.state.playing === false) {
const { navigation } = this.props;
const jsonReceived = navigation.getParam('item', {})
return(
<ImageBackground style={{width:"100%",height:"100%",alignItems:"center",justifyContent:"center"}} source={{uri:jsonReceived.video_banner}}>
<TouchableOpacity
onPress={() => {
this.setState({playing:true})
}}
>
<Image source={require("../assets/Common/Play/playIcon.png")}/>
</TouchableOpacity>
</ImageBackground>
)
} else if (this.state.videoFileArr.length > 0 && this.state.playing === true) {
return (
<View style={styles.container}>
<Video source={{ uri:this.state.videoFileArr[0].link}} // Can be a URL or a local file.
ref={ ref =>
this.player = ref
} // Store reference
onBuffer={this.onBuffer} // Callback when remote video is buffering
onError={this.videoError} // Callback when video cannot be loaded
style={styles.backgroundVideo}
controls={true}
paused={false}
fullscreen={true}
/>
</View>
)
}
}
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1, overflow: "hidden" }}>
<View style={{ flex: 1, backgroundColor: "green" }}>
{this.renderOptions()}
</View>
{/* top navigationBar */}
<View
style={{
position: "absolute",
top: 0,
left: 0,
right: 0,
width: "100%",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
height: 80,
backgroundColor: null
}}
>
<TouchableOpacity onPress={
()=>this.goToHome()
}>
<Image style={{ margin: 8 }} source={require("../assets/Common/goBack/goBack.png")} />
</TouchableOpacity>
<TouchableOpacity>
<Image style={{ margin: 8 }} source={require("../assets/Common/Star/starOff.png")} />
</TouchableOpacity>
</View>
</View>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container:{ flex: 1, justifyContent: "center"},
backgroundVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
});
and this is the output screen where I can not play video in full screen:
Please help, What I'm doing wrong ?
I have solved fullscreen of video frame just adding resizeMode on Video component:
<Video source={{ uri:this.state.videoFileArr[0].link}} // Can be a URL or a local file.
ref={ ref =>
this.player = ref
} // Store reference
onBuffer={this.onBuffer} // Callback when remote video is buffering
onError={this.videoError} // Callback when video cannot be loaded
style={styles.backgroundVideo}
controls={true}
paused={false}
fullscreen={true}
resizeMode="cover"
/>
I was struggling with the same problem couple of days ago but I made it work for me in android. I hope this will help you also.
You will need to install some other package as well that is
1. react-native-video-controls
2. react-native-orientation
now In your Screen where the video will be played.
import React, { Component } from 'react'
import {
Text,
StyleSheet,
StatusBar,
Dimensions,
Alert,
Modal,
BackHandler,
TouchableOpacity,
ToastAndroid,
} from 'react-native'
import { Container, View, Button, Icon, List, ListItem } from 'native-base';
import Video from 'react-native-video';
import Orientation from 'react-native-orientation';
const sample = require('../assets/demo.mp4');
export default class Player extends Component {
constructor(props) {
super(props);
this.onLoad = this.onLoad.bind(this);
this.onProgress = this.onProgress.bind(this);
}
state = {
rate: 1,
volume: 1,
muted: false,
resizeMode: 'contain',
duration: 0.0,
currentTime: 0.0,
active: false,
modalVisible: false,
fullScreen: true,
};
onLoad(data) {
this.setState({ duration: data.duration });
}
onProgress(data) {
this.setState({ currentTime: data.currentTime });
}
getCurrentTimePercentage() {
if (this.state.currentTime > 0) {
return parseFloat(this.state.currentTime) / parseFloat(this.state.duration);
} else {
return 0;
}
}
renderRateControl(rate) {
const isSelected = (this.state.rate == rate);
return (
<ListItem>
<TouchableOpacity onPress={() => { this.setState({ rate: rate }) }}>
<Text style={{ fontWeight: isSelected ? "bold" : "normal" }}>
{rate}x
</Text>
</TouchableOpacity>
</ListItem>
)
}
renderResizeModeControl(resizeMode) {
const isSelected = (this.state.resizeMode == resizeMode);
return (
<TouchableOpacity onPress={() => { this.setState({ resizeMode: resizeMode })
}}>
<Text style={[styles.controlOption, { fontWeight: isSelected ? "bold" :
"normal" }]}>
{resizeMode}
</Text>
</TouchableOpacity>
)
}
setModalVisible = (visible) => {
this.setState({ modalVisible: visible });
}
fullScreen = () => {
Orientation.getOrientation((err, orientation) => {
if (orientation == 'LANDSCAPE') {
Orientation.lockToPortrait();
} else {
Orientation.lockToLandscape();
}
});
}
backAction = () => {
Orientation.getOrientation((err, orientation) => {
if (orientation == 'LANDSCAPE') {
Orientation.lockToPortrait();
}
});
};
componentDidMount() {
this.backHandler = BackHandler.addEventListener(
"hardwareBackPress",
this.backAction
);
}
componentWillUnmount() {
this.backHandler.remove();
}
render() {
const { modalVisible, paused } = this.state
const url = `https://www.sample-
videos.com/video/mp4/720/big_buck_bunny_720p_10mb.mp4`;
const flexCompleted = this.getCurrentTimePercentage() * 100;
const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
return (
<View style={styles.container}>
<StatusBar hidden={true} />
<Video source={sample}
style={styles.fullScreen}
rate={this.state.rate}
paused={this.state.paused}
volume={this.state.volume}
muted={this.state.muted}
resizeMode={this.state.resizeMode}
onLoad={this.onLoad}
onProgress={this.onProgress}
onEnd={() => { alert('Done!') }}
controls
repeat={true} />
<View style={[{ left: 0 }, styles.rateControl]}>
<Button
transparent
onPress={() => {
this.fullScreen();
}}
>
<Icon type="FontAwesome5" name="compress" style={{ color: "#fff",
fontSize: 15 }} />
</Button>
</View>
<View style={styles.rateControl}>
<Button
transparent
onPress={() => {
this.setModalVisible(true);
}}
>
<Icon type="FontAwesome5" name="ellipsis-v" style={{ color:
"#fff", fontSize: 15 }} />
</Button>
</View>
{/* <View style={styles.controls}>
<View style={styles.generalControls}>
<View style={styles.resizeModeControl}>
{this.renderResizeModeControl('cover')}
{this.renderResizeModeControl('contain')}
{this.renderResizeModeControl('stretch')}
</View>
</View>
<View style={styles.trackingControls}>
<View style={styles.progress}>
<View style={[styles.innerProgressCompleted, { flex: flexCompleted }]} />
<View style={[styles.innerProgressRemaining, { flex: flexRemaining }]} />
</View>
</View>
</View> */}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<View style={styles.closeModal}>
<Button
transparent
onPress={() => { this.setModalVisible(!modalVisible);
}}
>
<Icon name="close" />
</Button>
</View>
<View>
<Text style={{ textAlign: 'center', fontWeight: 'bold'
}}>Play Rate</Text>
<List style={{ flexDirection: 'row', justifyContent:
'space-between', alignItems: 'center' }}>
{this.renderRateControl(0.25)}
{this.renderRateControl(0.5)}
{this.renderRateControl(1.0)}
{this.renderRateControl(1.5)}
{this.renderRateControl(2.0)}
</List>
</View>
</View>
</View>
</Modal>
</View >
)
}
}
const styles = StyleSheet.create({
backgroundVideo: {
// position: 'absolute',
// top: 0,
// left: 0,
// bottom: 0,
// right: 0,
width: Dimensions.get('window').width,
height: Dimensions.get('window').width * .6,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'black',
},
fullScreen: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
controls: {
backgroundColor: "transparent",
borderRadius: 5,
position: 'absolute',
bottom: 20,
left: 20,
right: 20,
},
progress: {
flex: 1,
flexDirection: 'row',
borderRadius: 3,
overflow: 'hidden',
},
innerProgressCompleted: {
height: 20,
backgroundColor: '#cccccc',
},
innerProgressRemaining: {
height: 20,
backgroundColor: '#2C2C2C',
},
generalControls: {
flex: 1,
// flexDirection: 'row',
borderRadius: 4,
overflow: 'hidden',
paddingBottom: 10,
},
rateControl: {
flexDirection: 'row',
position: 'absolute',
top: 10,
right: 10
},
volumeControl: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
},
resizeModeControl: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
controlOption: {
alignSelf: 'center',
fontSize: 11,
color: "white",
paddingLeft: 2,
paddingRight: 2,
lineHeight: 12,
},
centeredView: {
flex: 1,
marginTop: '22%'
},
modalView: {
width: '100%',
padding: '5%',
backgroundColor: "white",
position: 'absolute',
bottom: 10,
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2
},
closeModal: {
alignItems: 'flex-end',
margin: -10
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center"
},
modalText: {
marginBottom: 15,
textAlign: "center"
}
});
I hope this will help you.
Most of suggestion involves adding additional libraries to achieve fullscreen in react-native-vide for android. Its not really needed.
What we need is set the height and width of to full screen to achieve this. we need to use variable instead of fixed value then setState to refresh the view.
Below is the sample typescript code that works for react-native-video fullscreen:
import React, {Component} from 'react';
import {
View,
StyleSheet,
TouchableWithoutFeedback,
Dimensions,
} from 'react-native';
import Video from 'react-native-video';
import Icon from 'react-native-vector-icons/FontAwesome';
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons';
interface Props {}
interface States {
paused: boolean;
inFullScreen: boolean;
}
export default class Sandbox extends Component<Props, States> {
player: any;
videoStyle: {minWidth: number; minHeight: number};
constructor(props: Props) {
super(props);
this.state = {
paused: true,
inFullScreen: false,
};
this.videoStyle = {minWidth: 400, minHeight: 400};
}
render() {
return (
<View style={{height: 400, width: 400}}>
<Video
source={{
uri:
'https://www.radiantmediaplayer.com/media/big-buck-bunny-360p.mp4',
}} // Can be a URL or a local file.
ref={(ref: any) => {
this.player = ref;
}} // Store reference
controls={false}
paused={this.state.paused}
resizeMode={'cover'}
style={this.videoStyle}
/>
<View style={styles.controls}>
<TouchableWithoutFeedback
onPress={() => {
this.setState({paused: !this.state.paused});
}}>
<Icon name={'play'} size={30} color="#FFF" />
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => {
if (!this.state.inFullScreen) {
//Orientation.lockToLandscape();
this.videoStyle = {
minHeight: Dimensions.get('window').height,
minWidth: Dimensions.get('window').width,
};
} else {
this.videoStyle = {
minHeight: 400,
minWidth: 400,
};
}
this.setState({inFullScreen: !this.state.inFullScreen});
}}>
<MaterialIcon name={'fullscreen'} size={30} color="#FFF" />
</TouchableWithoutFeedback>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
controls: {
backgroundColor: 'rgba(0, 0, 0, 0.5)',
height: 48,
top: 20,
left: 0,
bottom: 0,
right: 0,
position: 'absolute',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
paddingHorizontal: 10,
},
});
As #Selva answered we can use variables for video sizes i.e width & height and make it occupy full screen and use a stack to place the video in a stack screen above the current screen and pop it when needed. Even if it's in a flat list.
Had same issue fix it by removing the wrapping and setting just the height to the player, no other library needed and no need to manage the orientation.
<Video source={{uri: this.props.videoData.uri}}
onEnd={this.onVideoEnd}
style={styles.player}
controls={true} />
<View
onStartShouldSetResponder={() => setPaused(!paused)}
style={{
marginHorizontal: 10,
backgroundColor: "black",
position: "relative",
transform: [{ rotate: "90deg" }],
// justifyContent:'center',
// alignItems:'center'
}}
>
<Video
onEnd={onEnd}
onLoad={onLoad}
onLoadStart={onLoadStart}
posterResizeMode={"cover"}
onProgress={onProgress}
paused={paused}
ref={(ref) => (videoPlayer.current = ref)}
resizeMode={'stretch'}
source={{
uri: "url",
}}
style={{
...styles.backgroundVideo,
height: width,
aspectRatio:2
// width: "100%"
// alignSelf:'center'
// transform: [{ rotate: '90deg'}]
}}
/>
just give it a width of
width:'100%'
It seems that using WebView to open google maps(i.e. https://maps.google.com) will cause a fatal error. The function 'onNavigationStateChange' will be called infinite times. I print the navState parameter to log and the following is the output:
Log Output
Here is my code, which was modified from WebView Example.
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
TextInput,
TouchableWithoutFeedback,
TouchableOpacity,
View,
WebView
} = ReactNative;
var HEADER = '#3b5998';
var BGWASH = 'rgba(255,255,255,0.8)';
var DISABLED_WASH = 'rgba(255,255,255,0.25)';
var TEXT_INPUT_REF = 'urlInput';
var WEBVIEW_REF = 'webview';
var DEFAULT_URL = 'https://maps.google.com';
var WebViewExample = React.createClass({
getInitialState: function() {
return {
url: DEFAULT_URL,
status: 'No Page Loaded',
backButtonEnabled: false,
forwardButtonEnabled: false,
loading: true,
scalesPageToFit: true,
};
},
inputText: '',
handleTextInputChange: function(event) {
var url = event.nativeEvent.text;
if (!/^[a-zA-Z-_]+:/.test(url)) {
url = 'http://' + url;
}
this.inputText = url;
},
render: function() {
this.inputText = this.state.url;
return (
<View style={[styles.container]}>
<View style={[styles.addressBarRow]}>
<TouchableOpacity
onPress={this.goBack}
style={this.state.backButtonEnabled ? styles.navButton : styles.disabledButton}>
<Text>
{'<'}
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.goForward}
style={this.state.forwardButtonEnabled ? styles.navButton : styles.disabledButton}>
<Text>
{'>'}
</Text>
</TouchableOpacity>
<TextInput
ref={TEXT_INPUT_REF}
autoCapitalize="none"
defaultValue={this.state.url}
onSubmitEditing={this.onSubmitEditing}
onChange={this.handleTextInputChange}
clearButtonMode="while-editing"
style={styles.addressBarTextInput}
/>
<TouchableOpacity onPress={this.pressGoButton}>
<View style={styles.goButton}>
<Text>
Go!
</Text>
</View>
</TouchableOpacity>
</View>
<WebView
ref={WEBVIEW_REF}
automaticallyAdjustContentInsets={false}
style={styles.webView}
source={{uri: this.state.url}}
javaScriptEnabled={true}
domStorageEnabled={true}
decelerationRate="normal"
onNavigationStateChange={this.onNavigationStateChange}
onShouldStartLoadWithRequest={this.onShouldStartLoadWithRequest}
startInLoadingState={true}
scalesPageToFit={this.state.scalesPageToFit}
/>
<View style={styles.statusBar}>
<Text style={styles.statusBarText}>{this.state.status}</Text>
</View>
</View>
);
},
goBack: function() {
this.refs[WEBVIEW_REF].goBack();
},
goForward: function() {
this.refs[WEBVIEW_REF].goForward();
},
reload: function() {
this.refs[WEBVIEW_REF].reload();
},
onShouldStartLoadWithRequest: function(event) {
// Implement any custom loading logic here, don't forget to return!
return true;
},
onNavigationStateChange: function(navState) {
console.log(navState);
this.setState({
backButtonEnabled: navState.canGoBack,
forwardButtonEnabled: navState.canGoForward,
url: navState.url,
status: navState.title,
loading: navState.loading,
scalesPageToFit: true
});
},
onSubmitEditing: function(event) {
this.pressGoButton();
},
pressGoButton: function() {
var url = this.inputText.toLowerCase();
if (url === this.state.url) {
this.reload();
} else {
this.setState({
url: url,
});
}
// dismiss keyboard
this.refs[TEXT_INPUT_REF].blur();
},
});
var Button = React.createClass({
_handlePress: function() {
if (this.props.enabled !== false && this.props.onPress) {
this.props.onPress();
}
},
render: function() {
return (
<TouchableWithoutFeedback onPress={this._handlePress}>
<View style={[styles.button, this.props.enabled ? {} : styles.buttonDisabled]}>
<Text style={styles.buttonText}>{this.props.text}</Text>
</View>
</TouchableWithoutFeedback>
);
}
});
var ScaledWebView = React.createClass({
getInitialState: function() {
return {
scalingEnabled: true,
}
},
render: function() {
return (
<View>
<WebView
style={{
backgroundColor: BGWASH,
height: 200,
}}
source={{uri: 'https://facebook.github.io/react/'}}
scalesPageToFit={this.state.scalingEnabled}
/>
<View style={styles.buttons}>
{ this.state.scalingEnabled ?
<Button
text="Scaling:ON"
enabled={true}
onPress={() => this.setState({scalingEnabled: false})}
/> :
<Button
text="Scaling:OFF"
enabled={true}
onPress={() => this.setState({scalingEnabled: true})}
/> }
</View>
</View>
);
},
})
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: HEADER,
},
addressBarRow: {
flexDirection: 'row',
padding: 8,
},
webView: {
backgroundColor: BGWASH,
height: 350,
},
addressBarTextInput: {
backgroundColor: BGWASH,
borderColor: 'transparent',
borderRadius: 3,
borderWidth: 1,
height: 24,
paddingLeft: 10,
paddingTop: 3,
paddingBottom: 3,
flex: 1,
fontSize: 14,
},
navButton: {
width: 20,
padding: 3,
marginRight: 3,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: BGWASH,
borderColor: 'transparent',
borderRadius: 3,
},
disabledButton: {
width: 20,
padding: 3,
marginRight: 3,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: DISABLED_WASH,
borderColor: 'transparent',
borderRadius: 3,
},
goButton: {
height: 24,
padding: 3,
marginLeft: 8,
alignItems: 'center',
backgroundColor: BGWASH,
borderColor: 'transparent',
borderRadius: 3,
alignSelf: 'stretch',
},
statusBar: {
flexDirection: 'row',
alignItems: 'center',
paddingLeft: 5,
height: 22,
},
statusBarText: {
color: 'white',
fontSize: 13,
},
spinner: {
width: 20,
marginRight: 6,
},
buttons: {
flexDirection: 'row',
height: 30,
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'space-between',
},
button: {
flex: 0.5,
width: 0,
margin: 5,
borderColor: 'gray',
borderWidth: 1,
backgroundColor: 'gray',
},
});
const HTML = `
<!DOCTYPE html>\n
<html>
<head>
<title>Hello Static World</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=320, user-scalable=no">
<style type="text/css">
body {
margin: 0;
padding: 0;
font: 62.5% arial, sans-serif;
background: #ccc;
}
h1 {
padding: 45px;
margin: 0;
text-align: center;
color: #33f;
}
</style>
</head>
<body>
<h1>Hello Static World</h1>
</body>
</html>
`;
exports.displayName = (undefined: ?string);
exports.title = '<WebView>';
exports.description = 'Base component to display web content';
exports.examples = [
{
title: 'Simple Browser',
render(): ReactElement<any> { return <WebViewExample />; }
},
{
title: 'Scale Page to Fit',
render(): ReactElement<any> { return <ScaledWebView/>; }
},
{
title: 'Bundled HTML',
render(): ReactElement<any> {
return (
<WebView
style={{
backgroundColor: BGWASH,
height: 100,
}}
source={require('./helloworld.html')}
scalesPageToFit={true}
/>
);
}
},
{
title: 'Static HTML',
render(): ReactElement<any> {
return (
<WebView
style={{
backgroundColor: BGWASH,
height: 100,
}}
source={{html: HTML}}
scalesPageToFit={true}
/>
);
}
},
{
title: 'POST Test',
render(): ReactElement<any> {
return (
<WebView
style={{
backgroundColor: BGWASH,
height: 100,
}}
source={{
uri: 'http://www.posttestserver.com/post.php',
method: 'POST',
body: 'foo=bar&bar=foo'
}}
scalesPageToFit={false}
/>
);
}
}
];
AppRegistry.registerComponent('test', () => WebViewExample);
If anyone can help me fix this problem, I would be really appreciated!
Don't know if you fix it, but here is an option if you want :
-Using <Mapview> and react-native-maps : look here