最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Change color of TouchableOpacity in React Native - Stack Overflow

programmeradmin1浏览0评论

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.

Share Improve this question edited Dec 6, 2019 at 5:14 akhtarvahid 9,7692 gold badges29 silver badges33 bronze badges asked Dec 6, 2019 at 4:51 Jasur KurbanovJasur Kurbanov 8403 gold badges11 silver badges23 bronze badges 9
  • 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
 |  Show 4 more comments

5 Answers 5

Reset to default 5

Try 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;

发布评论

评论列表(0)

  1. 暂无评论