Can anyone help me. This is my source code:
Idea is that, if I click to "1 Button" it should be 'red' and if I click to "2 Button" is also should change its color to 'red' but the "1 Button" should be changed to its default colour which is black. However, "2 Button".
If my approach is too simple, other methods (such as TouchableHighlight
, ES6 and etc) are also welcomed. I appreciate if you show me mistakes so that I learn from that.
Can anyone help me. This is my source code: https://snack.expo.io/rJFgyPDpH
Idea is that, if I click to "1 Button" it should be 'red' and if I click to "2 Button" is also should change its color to 'red' but the "1 Button" should be changed to its default colour which is black. However, "2 Button".
If my approach is too simple, other methods (such as TouchableHighlight
, ES6 and etc) are also welcomed. I appreciate if you show me mistakes so that I learn from that.
- 1 there is no button/touchable opacity in your app...please have a look once in your code – abhikumar22 Commented Dec 6, 2019 at 4:54
- Thank you for mentioning, I updated, check it out – Jasur Kurbanov Commented Dec 6, 2019 at 4:55
- can you pease state what you want....it is not clear in your question...please elaborate on the cases you want – abhikumar22 Commented Dec 6, 2019 at 4:58
- 1 so you want alternative button color change for both the button....if one is black and another is red then clicking on anyone will reverses the color of the button? – abhikumar22 Commented Dec 6, 2019 at 5:16
- 1 initially both will be black? – abhikumar22 Commented Dec 6, 2019 at 5:20
5 Answers
Reset to default 5Try below
state={
selectedButton: '',
};
<View style={styles.container}>
<TouchableOpacity
style={{ backgroundColor: this.state.selectedButton === 'button1' ? 'red' : 'black', padding: 15}}
onPress={() => this.setState({ selectedButton: 'button1' })}
>
<Text style={styles.text}>1 Button</Text>
</TouchableOpacity>
<TouchableOpacity
style={{ backgroundColor: this.state.selectedButton === 'button2' ? 'red' : 'black', padding: 15}}
onPress={() => this.setState({ selectedButton: 'button2' })}
>
<Text style={styles.text}>2 button!</Text>
</TouchableOpacity>
</View>
You can write your code like:
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button,TouchableOpacity} from 'react-native';
export default class App extends Component {
state={
backgroundColor: 'black',
backgroundColor2: 'black',
pressed: false,
};
changeColor(){
if(!this.state.pressed){
this.setState({ pressed: true,backgroundColor: 'red', backgroundColor2: 'black'});
} else {
this.setState({ pressed: false, backgroundColor: 'black' ,backgroundColor2: 'red'});
}
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={{backgroundColor:this.state.backgroundColor, padding: 15}}
onPress={()=>this.changeColor()}
>
<Text style={styles.text}>1 Button</Text>
</TouchableOpacity>
<TouchableOpacity
style={{backgroundColor:this.state.backgroundColor2, padding: 15}}
onPress={()=>this.changeColor()}
>
<Text style={styles.text}>2 button!</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
text:{
color:'white'
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
});
Now If you click to the first button it should be 'red', but second, remains as 'black' background. Consequently, if you click to second button it should be 'red', whereas the first button should be 'black'.
changeColor=()=>{
this.setState({
backgroundColor:'red',
backgroundColor2:'black'
})
}
changeColor2=()=>{
this.setState({
backgroundColor:'black',
backgroundColor2:'red'
})
}
As per your requirements, onPress on first button, it will invoke changeColor. And onPress of second button, it'll invoke changeColor2.
In the code, onPress of second button, it can be changed to changeColor2 instead of changeColor function.
This
onPress={()=>this.changeColor2()}
instead of
onPress={()=>this.changeColor()}
By passing id you can change color alternatively
import React, { Component } from 'react';
import { StyleSheet, TouchableOpacity, Text, View, Button } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = { colorId:0 };
}
onPress = (id) => {
this.setState({colorId: id});
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={this.state.colorId === 1? styles.red : styles.button}
onPress={()=>this.onPress(1)}>
<Text>Button1</Text>
</TouchableOpacity>
<TouchableOpacity
style={this.state.colorId === 2? styles.red : styles.button}
onPress={()=>this.onPress(2)}>
<Text>Button2</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 10,
},
red: {
backgroundColor: 'red',
alignItems: 'center',
padding: 10,
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
},
});
Live demo
So all the current approaches manage state with the onPress.
If you view the docs at: https://reactnative.dev/docs/touchableopacity
The TouchOpacity component inherits all the props of https://reactnative.dev/docs/touchablewithoutfeedback#props
Which means you have access to onPressIn and onPressOut which I personally use to manage the state instead of onPress.
Here is my probably overly complicated example, I am using drop shadows and gradients as well:
import React, {FC, FormEvent, ReactNode, useState} from 'react';
import {ActivityIndicator, GestureResponderEvent} from 'react-native';
import styled from '@emotion/native';
import LinearGradient from 'react-native-linear-gradient';
import DropShadow from "react-native-drop-shadow";
import {Theme, useTheme} from "@emotion/react";
import {adjustColor} from "../../helpers";
interface StyledProps {
fullWidth?: boolean;
variant?: string;
activeVariant?: string;
borderRadius?: string;
width?: string;
height?: string;
padding?: string;
fontSize?: string;
fontWeight?: string;
colors?: string[];
gradient?: boolean;
active?: boolean;
isLoading?: boolean;
}
interface ButtonProps<T = GestureResponderEvent> extends StyledProps {
onPress: ((event: T) => void) | undefined;
children: ReactNode;
}
const dropShadowProps = {
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 0,
},
shadowOpacity: .2,
shadowRadius: 5
}
const Button: FC<ButtonProps> = (props) => {
const theme = useTheme();
const {onPress, isLoading, children, ...rest} = props;
const [active, setActive] = useState<boolean>(false);
const handleOnPress = (event: any) => {
onPress && onPress(event);
};
return (
<StyledButton {...rest}
onPress={handleOnPress}
onPressIn={() => setActive(true)}
onPressOut={() => setActive(false)}
activeOpacity={props.activeVariant ? 1 : 0.2}
disabled={isLoading}
>
<DropShadow style={active ? {} : dropShadowProps}>
<StyledGradient colors={getBackgroundColors(props, active, theme)} {...rest}>
<StyledText {...rest} active={active}>
{children}
{isLoading ? (
<ActivityIndicator color={"#000"} />
) : null}
</StyledText>
</StyledGradient>
</DropShadow>
</StyledButton>
);
};
const getBackgroundColors = (props: StyledProps, active: boolean, theme: Theme) => {
const variant = active && props.activeVariant ? props.activeVariant : props.variant;
const colors = [];
switch (variant) {
case "primary":
colors.push(theme.colors.primary);
break;
default:
colors.push("#ffffff");
}
if (props.gradient) {
colors.push(adjustColor(colors[0], -15));
} else {
colors.push(colors[0]);
}
return colors;
}
const getColor = (props: any) => {
const variant = props.active && props.activeVariant ? props.activeVariant : props.variant;
switch (variant) {
case "primary":
return props.theme.colors.white;
default:
return props.theme.colors.black;
}
}
const StyledButton = styled.TouchableOpacity<StyledProps>`
width: ${props => props.fullWidth ? "100%" : props.width ? props.width : "auto"};
`
const StyledGradient = styled(LinearGradient)<StyledProps>`
width: ${props => props.fullWidth ? "100%" : props.width ? props.width : "auto"};
height: ${props => props.height ? props.height : "auto"};
border-radius: ${props => props.borderRadius ? props.borderRadius : "8px"};
display: flex;
justify-content: center;
align-items: center;
`;
const StyledText = styled.Text<StyledProps>`
color: ${props => getColor(props)};
font-size: ${props => props.fontSize ? props.fontSize : "16px"};
font-weight: ${props => props.fontWeight ? props.fontWeight : "400"};
padding: ${props => props.padding ? props.padding : "17px"};
line-height: ${props => props.fontSize ? props.fontSize : "16px"};
`
export default Button;