I am using linear gradient from lottie, the code is working fine with ios but in android its not fitting to full screen, there is some kind of padding between gradient and the view.
On ios its working fine...i tried many ways,
buy including padding to 0 and even margin to -20, but nothing worked...any solution?
import React, { Component } from 'react';
import {
Text,
StyleSheet,
View,
Platform,
Dimensions
} from 'react-native';
import SignInScreen from './src/screens/auth/SignInScreen';
import Animation from 'lottie-react-native';
import anim from './assets/gradient_animated_background.json';
const height = Dimensions.get('window').height + 20;
const width = Dimensions.get('window').width + 20;
export default class App extends Component {
componentDidMount() {
this.animation.play();
}
render() {
return (
<View style={styles.container}>
<Animation
ref={animation => {
this.animation = animation;
}}
style={{
backgroundColor: 'red',
height: '100%',
width: '100%'
}}
loop={true}
source={Platform.OS === 'ios' ? anim : 'gradient_animated_background.json'}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'blue',
flex: 1,
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
color: '#ffffff'
}
});
The animation, and when ever i keep changing the width and height..it forcefully tries to maintain the aspect radio...(not sure though)
{"v":"4.6.10","fr":15,"ip":0,"op":155,"w":1080,"h":1920,"nm":"background","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[540,960,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1160,880]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect"},{"ty":"st","c":{"a":0,"k":[0.9960784,0.7843137,0.145098,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"gf","o":{"a":0,"k":100},"r":1,"g":{"p":3,"k":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[0,0.511,0.89,0.283,0.5,0.334,0.873,0.583,1,0.156,0.857,0.882],"e":[0,0.726,0.283,0.89,0.5,0.441,0.356,0.886,1,0.156,0.429,0.882]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[0,0.726,0.283,0.89,0.5,0.441,0.356,0.886,1,0.156,0.429,0.882],"e":[0,0.89,0.283,0.283,0.5,0.886,0.553,0.219,1,0.882,0.823,0.156]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[0,0.89,0.283,0.283,0.5,0.886,0.553,0.219,1,0.882,0.823,0.156],"e":[0,0,0.312,0.737,0.5,0.078,0.597,0.754,1,0.156,0.882,0.771]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[0,0,0.312,0.737,0.5,0.078,0.597,0.754,1,0.156,0.882,0.771],"e":[0,0.51,0.89,0.282,0.5,0.333,0.873,0.582,1,0.157,0.855,0.882]},{"t":120}]}},"s":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[-430.769,-404.573],"e":[23.726,-364.48],"to":[75.7491683959961,6.68213844299316],"ti":[-123.915840148926,-8.51547145843506]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[23.726,-364.48],"e":[312.726,-353.48],"to":[123.915840148926,8.51547145843506],"ti":[-1.00208830833435,-1.83333337306976]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[312.726,-353.48],"e":[29.739,-353.48],"to":[1.00208830833435,1.83333337306976],"ti":[120.055290222168,0.60746711492538]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[29.739,-353.48],"e":[-407.606,-357.125],"to":[-120.055290222168,-0.60746711492538],"ti":[72.8907089233398,0.60746711492538]},{"t":120}]},"e":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[374.412,342.611],"e":[22.822,357.191],"to":[-58.5984153747559,2.42986845970154],"ti":[132.520950317383,-7.89707231521606]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[22.822,357.191],"e":[-420.714,389.994],"to":[-132.520950317383,7.89707231521606],"ti":[-4.68509674072266,-7.89707231521606]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[-420.714,389.994],"e":[50.932,404.573],"to":[4.68509674072266,7.89707231521606],"ti":[-132.918350219727,4.25226974487305]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[50.932,404.573],"e":[376.797,364.48],"to":[132.918350219727,-4.25226974487305],"ti":[-54.3107261657715,6.68213844299316]},{"t":120}]},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[93.29,219.491],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":155,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":1,"nm":"Deep Red Solid 1","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[540,960,0]},"a":{"a":0,"k":[540,960,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"sw":1080,"sh":1920,"sc":"#be2a2a","ip":0,"op":155,"st":0,"bm":0,"sr":1}]}
What you are missing is the resizeMode, which is not specified on the documentation page, but if you look at the source you'll find it.
Here's something that works if you don't care to lose a few pixels:
import React, { Component } from 'react';
import {
StyleSheet,
View,
Dimensions
} from 'react-native';
import LottieView from 'lottie-react-native';
import { anim } from './assets/animation.json';
const { height, width } = Dimensions.get('window')
export default class App extends Component {
componentDidMount() {
this.animation.play();
}
render() {
return (
<View style={styles.container}>
<LottieView
ref={animation => {
this.animation = animation;
}}
style={{
width: width + 10,
height: height,
marginLeft: - 5
}}
resizeMode='cover'
loop={true}
source={anim}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'blue',
flex: 1,
},
});
Notice that I've exported the asset a bit differently since I tried this on https://snack.expo.io and for some reason they don't like JSON files 😁, so now the assets look something
/assets/animation.json.js
export const anim = {"v":"4.6.10","fr":15,"ip":0,"op":155,"w":1080,"h":1920,"nm":"background","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[540,960,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1160,880]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect"},{"ty":"st","c":{"a":0,"k":[0.9960784,0.7843137,0.145098,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"gf","o":{"a":0,"k":100},"r":1,"g":{"p":3,"k":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[0,0.511,0.89,0.283,0.5,0.334,0.873,0.583,1,0.156,0.857,0.882],"e":[0,0.726,0.283,0.89,0.5,0.441,0.356,0.886,1,0.156,0.429,0.882]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[0,0.726,0.283,0.89,0.5,0.441,0.356,0.886,1,0.156,0.429,0.882],"e":[0,0.89,0.283,0.283,0.5,0.886,0.553,0.219,1,0.882,0.823,0.156]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[0,0.89,0.283,0.283,0.5,0.886,0.553,0.219,1,0.882,0.823,0.156],"e":[0,0,0.312,0.737,0.5,0.078,0.597,0.754,1,0.156,0.882,0.771]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[0,0,0.312,0.737,0.5,0.078,0.597,0.754,1,0.156,0.882,0.771],"e":[0,0.51,0.89,0.282,0.5,0.333,0.873,0.582,1,0.157,0.855,0.882]},{"t":120}]}},"s":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[-430.769,-404.573],"e":[23.726,-364.48],"to":[75.7491683959961,6.68213844299316],"ti":[-123.915840148926,-8.51547145843506]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[23.726,-364.48],"e":[312.726,-353.48],"to":[123.915840148926,8.51547145843506],"ti":[-1.00208830833435,-1.83333337306976]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[312.726,-353.48],"e":[29.739,-353.48],"to":[1.00208830833435,1.83333337306976],"ti":[120.055290222168,0.60746711492538]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[29.739,-353.48],"e":[-407.606,-357.125],"to":[-120.055290222168,-0.60746711492538],"ti":[72.8907089233398,0.60746711492538]},{"t":120}]},"e":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[374.412,342.611],"e":[22.822,357.191],"to":[-58.5984153747559,2.42986845970154],"ti":[132.520950317383,-7.89707231521606]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[22.822,357.191],"e":[-420.714,389.994],"to":[-132.520950317383,7.89707231521606],"ti":[-4.68509674072266,-7.89707231521606]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[-420.714,389.994],"e":[50.932,404.573],"to":[4.68509674072266,7.89707231521606],"ti":[-132.918350219727,4.25226974487305]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[50.932,404.573],"e":[376.797,364.48],"to":[132.918350219727,-4.25226974487305],"ti":[-54.3107261657715,6.68213844299316]},{"t":120}]},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[93.29,219.491],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":155,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":1,"nm":"Deep Red Solid 1","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[540,960,0]},"a":{"a":0,"k":[540,960,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"sw":1080,"sh":1920,"sc":"#be2a2a","ip":0,"op":155,"st":0,"bm":0,"sr":1}]}
So the first answer raised an important point (adding resizeMode="cover").
But that's not enough, If you test across several screens sizes, you might still find unwanted margins and spaces. I had this issue too,
Here's the simple solution:
Get the dimensions of the lottie file (e.g 300 X 600)
Set width only, then use aspectRatio to determine the height. (must)
Set flexGrow = 1 (must)
e.g
<LottieView
style={{
width: 300,
aspectRatio: 300 / 600,
flexGrow: 1,
alignSelf: 'center',
}}
resizeMode="cover"
ref={animation=> { this.animation = animation; }}
source={require ('./assets/animation.json')}
autoPlay={false}
loop={false}
/>
I guess the problem arises because you cant use width and height at the same time in the styling of the Lottie view.
So an easy workaround is to use the width and aspectRatio
Good luck!
Related
I am learning React Native and I am having trouble displaying the ImageBackground component.
The ImageBackground has source that points to an image in the same folder, despite this is still not visible unless I give the ImageBackground a height in number, because if I try to give it a height in % it still won't show itself.
Here is the code for the component execpt the style:
import React from 'react';
import { View, ImageBackground, StyleSheet, Text } from 'react-native';
export default function WelcomeScreen(props) {
return (
<View>
<Text>Welcome</Text>
<ImageBackground source={require('./background.jpg')} style={styles.background} />
</View>
);
}
Trying different ways to style it, the ImageBackground has different behaviors regarding showing itself:
This will not show ImageBackground:
const styles = StyleSheet.create({
background: {
flex: 1,
},
});
This won't either:
const styles = StyleSheet.create({
background: {
flex: 1,
height: '100%',
},
});
This will show it:
const styles = StyleSheet.create({
background: {
flex: 1,
height: 300,
},
});
I do not understand why this happens. From my understanding the size should be added only when the image is from the net, and regardless this, the % value should still work.
What am I missing here?
EDIT:
I made a workaround for this using Dimension and feeding the screen height to the ImageBackground:
import { View, ImageBackground, StyleSheet, Dimensions } from 'react-native';
const { height } = Dimensions.get('screen');
const styles = StyleSheet.create({
background: {
flex: 1,
height,
},
});
Though it works, the question why do I need to set a height for an image in the same folder still stand.
if you want to give a value in percentage in such cases you should use some tricks like:
background: {
height: deviceHeight,
},
container: {
height: deviceHeight * 50 / 100,
}
or you can use a popular library in the name of react-native-responsive-screen. This library is going to give you the power to give relative values and convert them to absolute values behind the scene.
The snippet below is going to show how to use it:
import {widthPercentageToDP, heightPercentageToDP} from 'react-native-responsive-screen';
const styles = StyleSheet.create({
background: {
height: heightPercentageToDP('100%'),
}
})
This should work as you expected ;)
If you want your background image to cover your entire view, try something like this:
<View>
<ImageBackground style={styles.image} resizeMode={'cover'} source={require('../Images/test.jpg')}>
{/*your components*/}
</ImageBackground>
</View>
with this styling:
const styles = StyleSheet.create({
image: {
height: '100%',
width: undefined,
}
})
Im trying to make an app for the weather in a certain place in the world given by lat and long. The thing is that when I check the screen the applicaction only shows like 1/5 in the center of the screen with the function executed to show the temperature.
Can't upload pictures because of my reputation. But imagine this is the screen: [----|||----] only the ||| portion shows.
I dont know much about react-native so im just searching and doing whatever somebody else do, i have tried forcing a view style "global" for the class but it seems itdoesnt work if you dont put it inside the render, return section which i cant move, atleast to the places i tried.
Didn't include the code inside the functions.
class WeatherScreen extends React.Component {
state = {
isLoading: true,
temperature: 0,
weatherCondition: null,
error: null
};
componentDidMount() {
...
}
fetchWeather(lat, lon) {
fetch(....
}
render() {
const { isLoading, weatherCondition, temperature } = this.state;
return (
<View style={styles.container}>
{isLoading ? (
<View style={styles.loadingContainer}>
<Text style={styles.loadingText}>Fetching The Weather</Text>
</View>
) : (
<Weather weather={weatherCondition} temperature={temperature}/>
)}
</View>
);
}
}
export default WeatherScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Do not apply alignItems and justifyContent to the main screen, it will bring your screen to center. If you want your content in the center then add these properties to children View of main container/View.
Also get screen width and height from react-native dimensions and add them to main container style(height, width).
Try this
import { Dimensions } from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
class YourClass extends Component {
...your code ...
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
height: height,
width: width
},
});
I have the following React-Native code which alerts the user that it was pressed, however it does not respond to anything.
I have tried using different Touchable components but none seem to work, the only one is Button but that's not really what I want, I'm building a slider so a button is not really appropriate for this.
Anyway, here's my code:
import React, {Component} from 'react';
import {View, TouchableWithoutFeedback, Alert, Text} from 'react-native';
import styles from './styles.js';
import LinearGradient from 'react-native-linear-gradient';
export default class BrightnessSlider extends Component {
value: 100;
constructor(...args) {
super(...args);
}
render() {
return (
<LinearGradient start={{x: 0, y: 0}} end={{x: 1, y: 0}} colors={["#222", "#ddd"]} style={styles.brightnessSliderRunnable}>
<View style={styles.brightnessSliderTrack}>
<TouchableWithoutFeedback onPress={() => Alert.alert("Hello World")}>
<View style={styles.brightnessSliderThumb} />
</TouchableWithoutFeedback>
</View>
</LinearGradient>
)
}
}
and ./styles.js
import {StyleSheet} from "react-native";
export default styles = StyleSheet.create({
brightnessSliderRunnable: {
top: 50,
height: 9,
width: width - 20,
left: 10,
backgroundColor: "#555",
opacity: 1,
elevation: 1,
borderWidth: 0
// position: "absolute"
},
brightnessSliderThumb: {
width: 23,
height: 23,
borderColor: "#888",
// opacity: 1,
borderWidth: 2,
backgroundColor: "#ffffff",
position: "absolute",
top: -7,
borderRadius: 5,
elevation: 2
},
brightnessSliderTrack: {
width: "100%",
elevation: 1,
borderWidth: 0
}
});
Thanks for any help
Questioner's original code.
Solution
Added by questioner's solution.
Change position: absolute to position: relative.
Change your style type made by StyleSheet as below.
Your original.
{...styles.colourContainer, opacity: 100 - this.darkness}
Recommend way.
[styles.colourContainer, {opacity: 100 - this.darkness}]
I tested code and it works well when we touch the white square.
Tested on iOS.
Original App.js.
App.js changed by me.
import React, {Component} from 'react';
import {View, Dimensions, Text} from 'react-native';
import BrightnessSlider from '../components/BrightnessSlider';
import styles from '../components/TempStyle.js';
const d = Dimensions.get('window'),
width = d.width,
height = d.height;
export default class BrightnessSliderTest extends Component {
constructor(...args) {
super(...args);
this.darkness = 0;
this.prevColours = ["#ff0000", "#00ff00", "#0000ff"];
}
render() {
// It is not possible just access the style created by StyleSheet.create(). Do not use StyleSheet.create() or change to flatten the StyleSheet object.
const sty = [styles.colourContainer,{ opacity: 100 - this.darkness}];
return (
<View style={styles.container}>
<View style={sty}>
<View style={styles.toolBar}>
<View style={styles.colourPalette}>
{this.prevColours.map((i, a) => <View key={String(a)} style={[styles.colourTile, {backgroundColor: i}]}/>)}
</View>
{/* <Button title={"Save To Palette"} onTap={this.saveToPalette}>Save</Button> */}
</View>
<BrightnessSlider />
</View>
</View>
);
}
}
Why?
I am not sure how you can use your component in other components. But if you do not have container having enough size can show your component, touch area may not work. That is why I use backgroundColor for container sometimes in testing.
Added after testing full code used in question.
It is not possible just access the style through like spread operator created by StyleSheet.create(). Do not use StyleSheet.create() or change to flatten the StyleSheet object.
And Style can be worked differently from platforms(iOS, Android).
From some reason I'm trying to set a big background and fit it to the mobile screen, I mean the width will be 100% and the height will be dynamic.
Also I have a bigger logo and I want to fit it into the screen so I gave it width & height but it's looks cut.. What i'm doing wrong? Just want a nice "Pre loader" screen with mean a background and logo in the middle..
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View, Image } from 'react-native';
export default class Preload extends Component {
render() {
return (
<View style={styles.mainBox}>
<Image source={require('../app_images/preload/bg.jpg')} style={styles.bgImage} />
<View><Image source={require('../app_images/preload/logo.png')} style={styles.logoImage} /></View>
</View>
);
}
}
const styles = StyleSheet.create({
mainBox:{
flex: 1,
alignItems:'center',
justifyContent:'center',
width: null,
height: null
},bgImage: {
position:'absolute',
top: 0,
left: 0,
alignSelf: 'stretch'
},logoImage: {
width: 100,
height: 150
}
});
AppRegistry.registerComponent('Preload', () => Preload);
Thanks!
For the logo, you should use contain resizeMode.
logoImage: {
width: 100,
height: 150,
resizeMode: 'contain'
}
For background mode, I think you can use cover and keep the view above it transparent
This is the style of the view that i have used
backCover: {
position: 'absolute',
marginTop: 20,
top: 0,
bottom: 0,
left: 0,
right: 0,
}
Currently it has a white background. I can change the backgroundColor as i want like '#343434' but it accepts only max 6 hexvalue for color so I cannot give opacity on that like '#00ffffff'. I tried using opacity like this
backCover: {
position: 'absolute',
marginTop: 20,
top: 0,
bottom: 0,
left: 0,
right: 0,
opacity: 0.5,
}
but it reduces visibility of view's content.
So any answers?
Use rgba value for the backgroundColor.
For example,
backgroundColor: 'rgba(52, 52, 52, 0.8)'
This sets it to a grey color with 80% opacity, which is derived from the opacity decimal, 0.8. This value can be anything from 0.0 to 1.0.
The following works fine:
backgroundColor: 'rgba(52, 52, 52, alpha)'
You could also try:
backgroundColor: 'transparent'
Try this backgroundColor: '#00000000'
it will set background color to transparent, it follows #rrggbbaa hex codes
Surprisingly no one told about this, which provides some !clarity:
style={{
backgroundColor: 'white',
opacity: 0.7
}}
Try to use transparent attribute value for making transparent background color.
backgroundColor: 'transparent'
You should be aware of the current conflicts that exists with iOS and RGBA backgrounds.
Summary: public React Native currently exposes the iOS layer shadow
properties more-or-less directly, however there are a number of
problems with this:
1) Performance when using these properties is poor by default. That's
because iOS calculates the shadow by getting the exact pixel mask of
the view, including any tranlucent content, and all of its subviews,
which is very CPU and GPU-intensive. 2) The iOS shadow properties do
not match the syntax or semantics of the CSS box-shadow standard, and
are unlikely to be possible to implement on Android. 3) We don't
expose the layer.shadowPath property, which is crucial to getting
good performance out of layer shadows.
This diff solves problem number 1) by implementing a default
shadowPath that matches the view border for views with an opaque
background. This improves the performance of shadows by optimizing for
the common usage case. I've also reinstated background color
propagation for views which have shadow props - this should help
ensure that this best-case scenario occurs more often.
For views with an explicit transparent background, the shadow will
continue to work as it did before ( shadowPath will be left unset,
and the shadow will be derived exactly from the pixels of the view and
its subviews). This is the worst-case path for performance, however,
so you should avoid it unless absolutely necessary. Support for this
may be disabled by default in future, or dropped altogether.
For translucent images, it is suggested that you bake the shadow into
the image itself, or use another mechanism to pre-generate the shadow.
For text shadows, you should use the textShadow properties, which work
cross-platform and have much better performance.
Problem number 2) will be solved in a future diff, possibly by
renaming the iOS shadowXXX properties to boxShadowXXX, and changing
the syntax and semantics to match the CSS standards.
Problem number 3) is now mostly moot, since we generate the shadowPath
automatically. In future, we may provide an iOS-specific prop to set
the path explicitly if there's a demand for more precise control of
the shadow.
Reviewed By: weicool
Commit: https://github.com/facebook/react-native/commit/e4c53c28aea7e067e48f5c8c0100c7cafc031b06
Adding reference of React-Native Version 0.64
Named colors
Named Colors: DOCS
In React Native you can also use color name strings as values.
Note: React Native only supports lowercase color names. Uppercase color names are not supported.
transparent#
This is a shortcut for rgba(0,0,0,0), same like in CSS3.
Hence you can do this:
background: {
backgroundColor: 'transparent'
},
Which is a shortcut of :
background: {
backgroundColor: 'rgba(0,0,0,0)'
},
In case you have hex color, you can convert it to rgba and set the opacity there:
const hexToRgbA = (hex, opacity) => {
let c;
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
c = hex.substring(1).split('');
if (c.length === 3) {
c = [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c = `0x${c.join('')}`;
return `rgba(${[(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',')},${opacity})`;
}
throw new Error('Bad Hex');
};
const color = '#1f8b7f'; // could be a variable
return (
<View style={{ backgroundColor: hexToRgbA(color, 0.1) }} />
)
source that helped me
This will do the trick help you,
Add one View element and add style as below to that view
.opaque{
position:'absolute',
backgroundColor: 'black',
opacity: 0.7,
zIndex:0
}
The best way to use background is hex code #rrggbbaa but it should be in hex.
Eg: 50% opacity means 256/2 =128, then convert that value(128) in HEX that will be 80,use #00000080 80 here means 50% transparent.
Here is my solution to a modal that can be rendered on any screen and initialized in App.tsx
ModalComponent.tsx
import React, { Component } from 'react';
import { Modal, Text, TouchableHighlight, View, StyleSheet, Platform } from 'react-native';
import EventEmitter from 'events';
// I keep localization files for strings and device metrics like height and width which are used for styling
import strings from '../../config/strings';
import metrics from '../../config/metrics';
const emitter = new EventEmitter();
export const _modalEmitter = emitter
export class ModalView extends Component {
state: {
modalVisible: boolean,
text: string,
callbackSubmit: any,
callbackCancel: any,
animation: any
}
constructor(props) {
super(props)
this.state = {
modalVisible: false,
text: "",
callbackSubmit: (() => {}),
callbackCancel: (() => {}),
animation: new Animated.Value(0)
}
}
componentDidMount() {
_modalEmitter.addListener(strings.modalOpen, (event) => {
var state = {
modalVisible: true,
text: event.text,
callbackSubmit: event.onSubmit,
callbackCancel: event.onClose,
animation: new Animated.Value(0)
}
this.setState(state)
})
_modalEmitter.addListener(strings.modalClose, (event) => {
var state = {
modalVisible: false,
text: "",
callbackSubmit: (() => {}),
callbackCancel: (() => {}),
animation: new Animated.Value(0)
}
this.setState(state)
})
}
componentWillUnmount() {
var state = {
modalVisible: false,
text: "",
callbackSubmit: (() => {}),
callbackCancel: (() => {})
}
this.setState(state)
}
closeModal = () => {
_modalEmitter.emit(strings.modalClose)
}
startAnimation=()=>{
Animated.timing(this.state.animation, {
toValue : 0.5,
duration : 500
}).start()
}
body = () => {
const animatedOpacity ={
opacity : this.state.animation
}
this.startAnimation()
return (
<View style={{ height: 0 }}>
<Modal
animationType="fade"
transparent={true}
visible={this.state.modalVisible}>
// render a transparent gray background over the whole screen and animate it to fade in, touchable opacity to close modal on click out
<Animated.View style={[styles.modalBackground, animatedOpacity]} >
<TouchableOpacity onPress={() => this.closeModal()} activeOpacity={1} style={[styles.modalBackground, {opacity: 1} ]} >
</TouchableOpacity>
</Animated.View>
// render an absolutely positioned modal component over that background
<View style={styles.modalContent}>
<View key="text_container">
<Text>{this.state.text}?</Text>
</View>
<View key="options_container">
// keep in mind the content styling is very minimal for this example, you can put in your own component here or style and make it behave as you wish
<TouchableOpacity
onPress={() => {
this.state.callbackSubmit();
}}>
<Text>Confirm</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.state.callbackCancel();
}}>
<Text>Cancel</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
);
}
render() {
return this.body()
}
}
// to center the modal on your screen
// top: metrics.DEVICE_HEIGHT/2 positions the top of the modal at the center of your screen
// however you wanna consider your modal's height and subtract half of that so that the
// center of the modal is centered not the top, additionally for 'ios' taking into consideration
// the 20px top bunny ears offset hence - (Platform.OS == 'ios'? 120 : 100)
// where 100 is half of the modal's height of 200
const styles = StyleSheet.create({
modalBackground: {
height: '100%',
width: '100%',
backgroundColor: 'gray',
zIndex: -1
},
modalContent: {
position: 'absolute',
alignSelf: 'center',
zIndex: 1,
top: metrics.DEVICE_HEIGHT/2 - (Platform.OS == 'ios'? 120 : 100),
justifyContent: 'center',
alignItems: 'center',
display: 'flex',
height: 200,
width: '80%',
borderRadius: 27,
backgroundColor: 'white',
opacity: 1
},
})
App.tsx render and import
import { ModalView } from './{your_path}/ModalComponent';
render() {
return (
<React.Fragment>
<StatusBar barStyle={'dark-content'} />
<AppRouter />
<ModalView />
</React.Fragment>
)
}
and to use it from any component
SomeComponent.tsx
import { _modalEmitter } from './{your_path}/ModalComponent'
// Some functions within your component
showModal(modalText, callbackOnSubmit, callbackOnClose) {
_modalEmitter.emit(strings.modalOpen, { text: modalText, onSubmit: callbackOnSubmit.bind(this), onClose: callbackOnClose.bind(this) })
}
closeModal() {
_modalEmitter.emit(strings.modalClose)
}
Hope I was able to help some of you, I used a very similar structure for in-app notifications
Happy coding