Related
im trying to create a personality picker as seen in the image below. The intended use of it is that depending on the score of each personality from 0 to 5 a black line will be drawn and expand to each of the five circles to indicate the score.
Here is my code so far to create this, I have gotten the circles in line and I am currently creating the black lines however I am unable to do them dynamically and I am having to plot each point specifically which may be a problem for different screensizes. I am hoping there is a better way than what I am doing right now as it is a tonne of nested Views forming shapes. Any help would be great on how to make this simpiler / more dynamic!
Thanks :)
return (
<View style={{margin: 32}}>
<Text style={{fontFamily: 'Roboto_400Regular', fontSize: 36}}>Plot your{"\n"}personality</Text>
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={{
fontFamily: 'Roboto_400Regular',
fontSize: 14,
color: '#878787',
paddingTop: 4,
alignSelf: 'flex-end'
}}>Use this to match with similar people?</Text>
<Switch
trackColor={{false: "#878787", true: "#5BF675"}}
thumbColor="#f4f3f4"
ios_backgroundColor="#878787"
onValueChange={toggleSwitch}
value={isEnabled}
/>
</View>
<View style={{alignItems: 'center', justifyContent: 'center', marginTop: 32}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 275,
width: 275,
borderRadius: 275 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 225,
width: 225,
borderRadius: 225 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 175,
width: 175,
borderRadius: 175 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 125,
width: 125,
borderRadius: 125 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 75,
width: 75,
borderRadius: 75 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{position: 'absolute', justifyContent: 'center', alignItems: 'center'}}>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '45deg'}],
position: 'absolute',
}}
/>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '90deg'}],
position: 'absolute',
}}
/>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '135deg'}],
position: 'absolute',
}}
/>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '180deg'}],
position: 'absolute',
}}
/>
<View style={{position: 'absolute', justifyContent: 'center', alignItems: 'center'}}>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: 90.5,
bottom: -3,
left: 0,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '0deg'}],
position: 'absolute',
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: 137.5,
bottom: -52,
right: -116,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '45deg'}],
position: 'absolute',
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: 137.5,
alignItems: 'center',
justifyContent: 'center',
bottom: -72,
left: -70,
transform: [{ rotate: '90deg'}],
position: 'absolute',
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: 137.5,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '135deg'}, {translateX: 68}],
position: 'absolute',
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: 137.5,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '180deg'}, {scaleX: 0}],
position: 'absolute',
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: 137.5,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '225deg'}, {translateX: 68}],
position: 'absolute',
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: 137.5,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '270deg'}, {translateX: 68}],
position: 'absolute',
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: (137.5),
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '315deg'}, {translateX: 68}],
position: 'absolute',
}}
/>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
);
I have found an answer, although I am not 100% satisfied and believe it may fall over when screens resize.
import React from 'react';
import {View} from "react-native";
interface PersonalityPlotterDialProps {
value: number
}
function PersonalityPlotterDial(props: PersonalityPlotterDialProps) {
const {value} = props;
const widthCalculator = (value: number) => {
switch (value) {
case 0:
return 0;
case 1:
return 37.5;
case 2:
return 62.5;
case 3:
return 87.5;
case 4:
return 112.5;
case 5:
return 137.5;
default:
return 0;
}
};
const translateCalculator = (value: number) => {
switch (value) {
case 0:
return 0;
case 1:
return 1.05;
case 2:
return 1.75;
case 3:
return 2.5;
case 4:
return 3.2;
case 5:
return 3.95;
default:
return 0;
}
}
const displayCalculator = () => {
if (widthCalculator(value) === 0) {
return 'none'
}
}
return (
<View style={{alignItems: 'center', justifyContent: 'center', marginTop: 32, marginBottom: 64}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 275,
width: 275,
borderRadius: 275 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 225,
width: 225,
borderRadius: 225 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 175,
width: 175,
borderRadius: 175 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 125,
width: 125,
borderRadius: 125 / 2,
alignItems: 'center',
justifyContent: 'center'
}}>
<View style={{
borderColor: '#DBDBDB',
borderWidth: 1,
height: 75,
width: 75,
borderRadius: 75 / 2,
alignItems: 'center',
justifyContent: 'center',
position: 'relative'
}}>
<View style={{position: 'absolute', justifyContent: 'center', alignItems: 'center'}}>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '45deg'}],
position: 'absolute',
}}
/>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '90deg'}],
position: 'absolute',
}}
/>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '135deg'}],
position: 'absolute',
}}
/>
<View
style={{
borderColor: '#DBDBDB',
borderWidth: 1,
width: 275,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '180deg'}],
position: 'absolute',
}}
/>
<View style={{position: 'absolute', justifyContent: 'center', alignItems: 'center'}}>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
bottom: -3,
left: 0,
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '0deg'}],
position: 'absolute',
display: displayCalculator(),
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '45deg'}, {translateX: (translateCalculator(value)) * 17.5}],
position: 'absolute',
display: displayCalculator(),
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '90deg'}, {translateX: (translateCalculator(value)) * 17.5}],
position: 'absolute',
display: displayCalculator(),
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '135deg'}, {translateX: (translateCalculator(value)) * 17.5}],
position: 'absolute',
display: displayCalculator(),
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
alignItems: 'center',
justifyContent: 'center',
bottom: -3,
right: 0,
transform: [{ rotate: '180deg'}],
position: 'absolute',
display: displayCalculator(),
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '225deg'}, {translateX: (translateCalculator(value)) * 17.5}],
position: 'absolute',
display: displayCalculator(),
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '270deg'}, {translateX: (translateCalculator(value)) * 17.5}],
position: 'absolute',
display: displayCalculator(),
}}
/>
<View
style={{
backgroundColor: '#000',
borderWidth: 3,
width: widthCalculator(value),
alignItems: 'center',
justifyContent: 'center',
transform: [{ rotate: '315deg'}, {translateX: (translateCalculator(value)) * 17.5}],
position: 'absolute',
display: displayCalculator(),
}}
/>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
);
}
export default PersonalityPlotterDial;
In general, there is a cleaner solution for this (maybe I will add one later), but for now, lets try and make your code work.
You can have dynamic line size by passing the width to each View component with a math formula. meaning, think of a way to represent the size of each line. for example:
0: 0px,
1: 50px,
2: 100px
and so on... (the 50px should be the radius divided by 5)
Now, for each View tag, you can just set the width by multiplying 50px with the value of the size of it(0-5: 0-250px).
This should do the trick.
(I assume you have a state or a way to keep the values of each label, and by that you multiply this value with 50px for each line)
Hey, sorry for taking so long I wasn't available so much. anyway, I wrote a small piece of code that does the behavior you want. the design isn't amazing but it does the trick. I used styled-components just for fun, you can run it easily by installing styled-component or just converting it to regular form:
App.js
import { useState } from 'react';
import styled from 'styled-components';
import Line from './components/line';
function App() {
const [values, setValues] = useState(config);
return (
<Container>
<Circle>
<Center/>
<Lines>{values.map((value) => <Line {...value} />)}</Lines></Circle>
<Menu>
{values.map((line, index) =>
<SizeButtons>
<Button onClick={() => {
const copyValues = [...values];
copyValues[index].value = line.value - 1 > 0 ? line.value - 1 : 0;
setValues(copyValues);
}}>-</Button>
<Button onClick={() => {
const copyValues = [...values];
copyValues[index].value = line.value + 1 < 5 ? line.value + 1 : 5;
setValues(copyValues);
}}>+</Button>
</SizeButtons>
)}
</Menu>
</Container>
);
}
export default App;
const Container = styled.div`
position: relative;
margin-top: 200px;
margin-left: 200px;
`;
const Circle = styled.div`
position: relative;
width: 250px;
height: 250px;
border: 1px solid black;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
`;
const Center = styled.div`
position: absolute;
top: 116px;
left: 116px;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: black;
`;
const Lines = styled.div`
position: absolute;
top: 125px;
left: 125px;
`;
const SizeButtons = styled.div``;
const Menu = styled.div`
position: absolute;
top: 0;
right: 0;
`;
const Button = styled.button``;
const config = [
{ value: 1, degree: 0 },
{ value: 1, degree: 45, },
{ value: 1, degree: 90, left: '2px' },
{ value: 1, degree: 135, top: '2px', left: '1px' },
{ value: 1, degree: 181, top: '2px' },
{ value: 1, degree: 225, top: '0px' },
{ value: 1, degree: 270, top: '0px' },
{ value: 1, degree: 315, top: '0px' },
]
line.js:
import React from 'react';
import styled from 'styled-components'
const Line = (props) => {
return (
<Container {...props}/>
);
};
export default Line;
const Container = styled.div`
width: ${props => props.value * 25 }px;
background: black;
height: 2px;
transform: rotate(${props => props.degree}deg);
transform-origin: top left;
position: absolute;
top: ${props => props.top};
left: ${props => props.left}
`;
let me know if something is unclear.
I am trying to have a focus area shape in my live camera like the picture below (circle is where one would take the image while everything out of the circle is darkened). I am currently using the expo camera exactly how it is shown in the code below. Does anyone know how I could add in a circle or square on top of this so that the user would know exactly where to take a picture of an object. Any help would be appreciated.
<View style={{ flex: 1 }}>
<Camera
style={{ flex: 1 }}
type={this.state.type}
flashMode={this.state.flashMode}
ref={(camera) => (this.camera = camera)}
zoom={this.state.cameraZoomValue}
autoFocus={Camera.Constants.AutoFocus.on}
whiteBalance={Camera.Constants.WhiteBalance.auto}
faceDetectorSettings={{
mode: FaceDetector.Constants.Mode.accurate,
detectLandmarks: FaceDetector.Constants.Landmarks.all,
runClassifications: FaceDetector.Constants.Classifications.all,
minDetectionInterval: 500,
tracking: true,
}}
onFacesDetected={this.onFacesDetected}
onFacesDetectionError={this.onFacesDetectionError}
>
</Camera>
</View>
you could try to add some view with border(top, left, right, bottom) and setting position absolutely to achieve it. Here is my code(not sort out very clean), but I think it could help.
import { StyleSheet, View ,Dimensions} from "react-native";
class App extends Component {
render() {
const { height, width } = Dimensions.get("window");
const maskRowHeight = Math.round((height - 200) / 20);
const maskColWidth = (width - 200) / 2;
return (
<View style={styles.app}>
<View style={styles.maskOutter}>
<View
style={[
{ flex: maskRowHeight },
styles.maskRow,
styles.maskFrame
]}
/>
<View style={[{ flex: 40 }, styles.maskCenter]}>
<View style={[{ width: maskColWidth }, styles.maskFrame]} />
<View style={styles.maskInner}>
<View
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: 10,
borderColor: "#FFFFFF",
borderTopWidth: 1,
}}
/>
<View
style={{
position: "absolute",
bottom: 0,
left: 0,
width: "100%",
height: 10,
borderColor: "#FFFFFF",
borderBottomWidth: 1,
}}
/>
<View
style={{
position: "absolute",
top: 0,
left: 0,
width: 20,
height: "100%",
borderColor: "#FFFFFF",
borderLeftWidth: 1,
}}
/>
<View
style={{
position: "absolute",
top: 0,
right: 0,
width: 20,
height: "100%",
borderColor: "#FFFFFF",
borderRightWidth: 1,
}}
/>
<View
style={{
position: "absolute",
top: 0,
left: 0,
width: 30,
height: 30,
borderColor: "#00BED6",
borderTopWidth: 4,
borderLeftWidth: 4
}}
/>
<View
style={{
position: "absolute",
top: 0,
right: 0,
width: 30,
height: 30,
borderColor: "#00BED6",
borderTopWidth: 4,
borderRightWidth: 4
}}
/>
<View
style={{
position: "absolute",
bottom: 0,
left: 0,
width: 30,
height: 30,
borderColor: "#00BED6",
borderBottomWidth: 4,
borderLeftWidth: 4
}}
/>
<View
style={{
position: "absolute",
bottom: 0,
right: 0,
width: 30,
height: 30,
borderColor: "#00BED6",
borderBottomWidth: 4,
borderRightWidth: 4
}}
/>
</View>
<View style={[{ width: maskColWidth }, styles.maskFrame]} />
</View>
<View
style={[
{ flex: maskRowHeight },
styles.maskRow,
styles.maskFrame
]}
>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
app: {
flex:1
},
cameraView: {
flex: 1,
justifyContent: "flex-start"
},
maskOutter: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
alignItems: "center",
justifyContent: "space-around"
},
maskInner: {
width: 300,
backgroundColor: "transparent"
},
maskFrame: {
backgroundColor: "#1C355E",
opacity: 0.7
},
maskRow: {
width: "100%"
},
maskCenter: { flexDirection: "row" },
rectangleText: {
justifyContent: "center",
alignItems: "center",
width: "100%",
flex: 1,
textAlign: "center",
color: "white"
}
});
export default App;
looks like this...
And you could change color what you want.
Code on sandbox
Trying to bring a button.js component to the front of my background carousel. Tried using zIndex, worked fine with my logo but not with my button?
Button code:
return (
<View style={styles.buttonContainer} >
<TouchableOpacity onPress={onPress} style={buttonStyle} >
<Text style={textStyle} >
{children}
</Text>
</TouchableOpacity>
</View>
);
const styles = {
buttonContainer: {
zIndex: 999,
alignItems: 'center'
},
buttonStyle: {
zIndex: 999,
position: 'absolute',
bottom: -200,
flex: .3,
alignSelf: 'auto',
backgroundColor: '#ffff00',
borderRadius: 10,
borderWidth: 1,
borderColor: '#000000',
marginLeft: 5,
marginRight: 5,
width: 250,
borderWidth: 1
},
textStyle: {
zIndex: 999,
alignSelf: 'center',
color: '#000000',
fontSize: 16,
fontWeight: '600',
paddingTop: 10,
paddingBottom: 10
}
};
export default Button;
Code for my app. Notice how i have literally added zIndex 999 for my button, and it still has not worked.
export default function App() {
return (
<View style={styles.carouselContainer}>
<BackgroundCarousel images={images}>
<View style={styles.logoContainer}>
<Image source={logo} style={styles.logo} />
<Text style={styles.logoText}>Hello World</Text>
</View>
<View>
<Button style={{ zIndex: 999 }}>
Let's Get Started
</Button>
</View>
</BackgroundCarousel>
</View>
);
}
const styles = StyleSheet.create({
carouselContainer: {
zIndex: 1,
height: "100%",
width: "100%",
backgroundColor: '#fff',
flex: 1
},
logoContainer: {
zIndex: 2,
alignItems: 'center',
position: 'absolute',
justifyContent: "center",
top: 0, left: 0, right: 0, bottom: 450
},
logo: {
zIndex: 2,
width: 125,
height: 125,
},
logoText: {
zIndex: 2,
color: 'black',
fontSize: 25,
fontWeight: '500',
borderColor: 'white',
fontFamily: "Baskerville-Bold",
},
button: {
flex: 1,
zIndex: 999,
}
});
Basically, is there another way to bring the button forward? Seeing as how zIndex is not working for me in this case.
z-index is only relative to that element's parent so as mentioned by #prakash-karena delete the view that surrounding your button.
<View style={styles.carouselContainer}>
<BackgroundCarousel images={images}>
<View style={styles.logoContainer}>
<Image source={logo} style={styles.logo} />
<Text style={styles.logoText}>Hello World</Text>
</View>
<Button style={{ zIndex: 999 }}>
Let's Get Started
</Button>
</BackgroundCarousel>
</View>
I believe zIndex is supported in the latest version of react native for iOS only, order that you place the elements in determines its layout order. you can try making overflow visible of scrollview.
enter image description hereenter image description herei'm Working on a view i have successfully shown the first color which is fixed i want another color to appear while on click of button. i have worked on dice and the total sum of two dice are showing . i want that whichever total number is coming it shows in the view as shown in image and that color changes.
this.state={
// This is our Default number value
NumberHolder : 1,
NumberHold : 1,
sum: 0,
}
}
GenerateRandomNumber = () => {
let RandomNumber = Math.floor(Math.random() * 6) + 1;
let RandomNumber1 = Math.floor(Math.random() * 6) + 1 ;
let sum = RandomNumber + RandomNumber1;
this.setState({
NumberHolder : RandomNumber,
NumberHold : RandomNumber1,
sum
});
}
getDice(diceNum) {
let diceSource = require(`./images/dice1.png`)
if (diceNum === 2) {
diceSource = require(`./images/dice2.png`)
} else if (diceNum === 3) {
diceSource = require(`./images/dice3.png`)
} else if (diceNum === 4) {
diceSource = require(`./images/dice4.png`)
} else if (diceNum === 5) {
diceSource = require(`./images/dice5.png`)
} else if (diceNum === 6) {
diceSource = require(`./images/dice6.png`)
} else {
diceSource = require(`./images/dice1.png`)
}
return (
<Image style={styles.dice}source={diceSource} />
)
}
render() {
// this is just for the demo purposes
const imageSize = this.state.NumberHolder * 50
return (
<View style={styles.MainContainer} >
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginRight:30,
}}>
<View style={{backgroundColor: '#006400'}}>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:40,
backgroundColor: '#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign:
'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
1
</Text>
</View>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:90,
borderWidth: 1,
borderColor: '#000000',
backgroundColor: '#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign:
'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
2
</Text>
</View>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:130,
borderWidth: 1,
borderColor: '#000000',
backgroundColor: '#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign:
'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
3
</Text>
</View>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:170,
borderWidth: 1,
borderColor: '#000000',
backgroundColor: '#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign: 'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
4
</Text>
</View>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:210,
borderWidth: 1,
borderColor: '#000000',
backgroundColor: '#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign:
'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
5
</Text>
</View>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:260,
backgroundColor: '#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign:
'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
6
</Text>
</View>
</View>
</View>
<View
style={{
borderBottomWidth: 2,
borderBottomColor: 'black',
width: 270,
marginLeft:18,
marginBottom:340,
}}
/>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:40,
marginTop:1
}}>
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
borderWidth: 1,
borderColor: '#000000',
marginTop:50,
backgroundColor: '#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign:
'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
7
</Text>
</View>
</View>
<Button style={{marginTop:40}} title="Roll again" onPress=
{this.GenerateRandomNumber} />
</View>
I want that whenever the total number is shown it shows in the view with different color.enter image description here
To change the color of a single view, based of a state variable, you just need to put a condition on the style prop.
For example:
<View style={{ position: 'absolute',
top: 0,
left: 20,
width: 50,
height: 50,
marginLeft:40,
backgroundColor: this.state.sum===1?"red":'#006400'}}>
<Text style={{justifyContent: 'center',flex: 1,textAlign:
'center',
marginTop:10,
color: '#ffffff',
alignItems: 'center'}}>
1
</Text>
</View>
As you have rendered them like that you have to do it on every View.
I would suggest to cycle trough a function to create a as they are all the same expect for the number.
toggleColor = () => {
this.setState(p => {
return {
flag: !p.flag
}
})
}
render() {
let color = 'red'
if (flag) { // you can change this condition to anything
color = 'green'
} else {
color = 'red'
}
return (
<View style={{backgroundColor:color}}></View>
)
}
I'm trying to have a popup dialog (created as a component with position: 'absolute') and to close it when user clicks outside of the popup.
I'm new to React Native so other things I did might be wrong, forgive me for that :)
This is a screenshot of the popup when it is open
This is some of the code:
From the Popup component:
render() {
if (!this.props.open) {
return <View />
}
return (
<View style={styles.container}>
<View style={styles.popupStyle}>
<View style={{flex:1, justifyContent: 'center', marginRight: 10}}>
<View style={styles.amountEnterStyle}>
<TextInput
keyboardType={'numeric'}
underlineColorAndroid='transparent'
autoCorrect={false}
style={styles.textInputStyle}
value={this.state.amount}
onChangeText={this._onAmountEnter.bind(this)} />
<Text style={styles.currencyTextStyle}>NIS</Text>
</View>
<View style={styles.separatorStyle} />
<View style={styles.categorySectionStyle}>
{this._renderCategoryDropdown()}
</View>
</View>
<View style={{justifyContent: 'center'}}>
<TouchableWithoutFeedback
onPress={this._onAddPaymentClicked.bind(this)} >
<View style={{width: 110, height:100, backgroundColor: "#ff0000"}} />
</TouchableWithoutFeedback>
</View>
</View>
</View>
);
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
width: undefined,
height: undefined,
justifyContent: 'center',
alignItems: 'center',
},
amountEnterStyle: {
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row'
},
textInputStyle: {
width: 100,
fontSize: 50,
fontWeight: 'bold',
height: 65,
flex: 1,
marginTop: -20,
paddingBottom: 0,
marginBottom: 0,
marginLeft:10,
textAlignVertical: 'center'
},
currencyTextStyle: {
fontSize: 50,
color: '#c0c0c0',
marginTop: -20,
textAlignVertical: 'center'
},
separatorStyle: {
height: 2,
marginTop: 0,
backgroundColor: '#c0c0c0',
},
categorySectionStyle: {
justifyContent: 'flex-start',
flexDirection: 'row',
alignItems: 'flex-start',
marginTop: 8
},
categoryColorDotStyle: {
width: 20,
height: 20,
borderRadius: 100/2,
marginLeft: 10,
marginTop: 5,
},
categoryTextStyle: {
fontSize: 24,
marginHorizontal: 4,
color: '#c0c0c0',
marginLeft: 10,
paddingRight: 10,
marginTop: -3
},
popupStyle: {
width: Dimensions.get('window').width - 60,
flexDirection: 'row',
justifyContent: 'space-between',
height: 150,
paddingRight:10,
paddingLeft:10,
borderRadius: 2,
margin: 20,
padding: 10,
opacity: 1,
borderRadius: 10,
backgroundColor: '#ffffff'
},
dropdownSeparator: {
height: 1,
backgroundColor: 'cornflowerblue'
},
And this is the hosting component:
render() {
var totalIncome = this.props.balance.totalIncome;
var totalExpanses = this.props.balance.totalExpanses;
return (
<View style={{flex:1, justifyContent: 'space-between'}}>
<Image pointerEvents='none' source={require('../../res/background.png')} style={styles.container} />
<MainScreenHeader onSettingPress={this._onBalanceSettingsPress.bind(this)}/>
<MainBalanceCounter totalCount={totalIncome} currentCount={totalIncome-totalExpanses} />
<View style={{justifyContent: 'center', alignItems: 'center', marginBottom: 150}}>
<AddPaymentButton onPress={this._onAddPaymentPress.bind(this)} />
<PaymentPopup
open={this.state.paymentPopupOpen}
onAddPaymentClicked={this._onPaymentPopupAddClicked.bind(this)} />
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
width: undefined,
height: undefined,
backgroundColor:'transparent',
justifyContent: 'center',
alignItems: 'center',
},
innerContainer: {
justifyContent: 'space-around',
alignItems: 'center',
flex: 1,
backgroundColor: 'transparent'
},
});
I was trying man things to have a view that will catch clicks that happens outside of the popup, but no success.
Any help will be much appreciated,
Thanks,
Giora.
have you tried out react-native-modalbox? I use it in my applications and it works pretty great. If you have touch events behind the modal, it will close. Also, you can define how large you'd like the modal to be. It doesn't have to take up the whole screen.
Otherwise, you were on the right track. You'd need a TouchableWithoutFeedback component that covers the full width and height of the screen. Your popup would be alongside of this component with a higher zIndex. Let me know if you'd like to go this route and I can provide more advice. Cheers!