在React Native中按下时改变按钮样式

60

当我的应用程序中的按钮被按下时,我希望它的样式能够改变。这个最好的方法是什么?


你需要在用户按下按钮时改变它,并在用户松开按钮时恢复原状吗?还是你需要在用户触摸按钮时改变它,并在触摸结束后保持改变的状态? - Nader Dabit
当用户没有按下时,要改回去。 - domi91c
这个解决方案对我有效。 - Maybelle Pacate
5个回答

68

使用TouchableHighlight

这里有一个例子:

enter image description here

import React from 'react';
import { TouchableHighlight, View, Text, StyleSheet } from 'react-native';

export default function Button() {

  var [ isPress, setIsPress ] = React.useState(false);

  var touchProps = {
    activeOpacity: 1,
    underlayColor: 'blue',                               // <-- "backgroundColor" will be always overwritten by "underlayColor"
    style: isPress ? styles.btnPress : styles.btnNormal, // <-- but you can still apply other style changes
    onHideUnderlay: () => setIsPress(false),
    onShowUnderlay: () => setIsPress(true),
    onPress: () => console.log('HELLO'),                 // <-- "onPress" is apparently required
  };

  return (
    <View style={styles.container}>
      <TouchableHighlight {...touchProps}>
        <Text>Click here</Text>
      </TouchableHighlight>
    </View>
  );
}

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  btnNormal: {
    borderColor: 'blue',
    borderWidth: 1,
    borderRadius: 10,
    height: 30,
    width: 100,
  },
  btnPress: {
    borderColor: 'blue',
    borderWidth: 1,
    height: 30,
    width: 100,
  }
});

这真的很有帮助!而且 onHideUnderlayonShowUnderlay 方法与 onPress 没有冲突。这让我有点困惑。 - Bruce Lee
7
请注意,自React Native v0.34以来,<TouchableHeighlight>必须包含一个onPress处理程序才能正常工作。 - rnevius
之前不知道 onHideUnderlayonShowUnderlay!一直在谷歌上搜索如何实现这样的功能。谢谢! - Greg Blass
使用这种方法,样式只会在您长按按钮后更改... 它不会仅在轻触时更改。 - P.Lorand
1
需要注意的是,为了使其正常工作,underlayColor 必须与 activeOpacity={1} 一起使用。 - instanceof
1
你是如何在点击时将文本颜色变为白色的? - user12314098

31

React Native现在提供了一个新的Pressable组件,可以检测不同阶段的按压交互。因此,要更改组件的颜色(通常是任何样式),请参考以下示例:

<Pressable
  style={({ pressed }) => [{ backgroundColor: pressed ? 'black' : 'white' }, styles.btn ]}>
  {({ pressed }) => (
    <Text style={[{ color: pressed ? 'white' : 'black' }, styles.btnText]}>
      {text}
    </Text>
  )}
</Pressable>

代码简介:

style={({ pressed }) => [{ backgroundColor: pressed ? 'black' : 'white' }, styles.btn ]}

这里的style属性接收布尔值pressed,反映了Pressable是否被按下,并返回一组样式。

{({ pressed }) => (
    <Text style={[{ color: pressed ? 'white' : 'black' }, styles.btnText]}>
      {text}
    </Text>
)}

在这里,文本样式也可以被修改,因为pressed属性也可以被Pressable组件的子组件访问。


16

1
underlayColor将以轻微的不透明度显示。将activeOpacity设置为0将完全忽略应用于未按下状态的任何样式。 - Naoto Ida

2

这是Besart Hoxhaj在ES6中的回答。当我回答这个问题时,React Native版本为0.34。

 import React from "react";
 import { TouchableHighlight, Text, Alert, StyleSheet } from "react-native";

 export default class TouchableButton extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        pressed: false
    };
}
render() {
    return (
        <TouchableHighlight
            onPress={() => {
                // Alert.alert(
                //     `You clicked this button`,
                //     'Hello World!',
                //     [
                //         {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
                //         {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
                //         {text: 'OK', onPress: () => console.log('OK Pressed')},
                //     ]
                // )
            }}
            style={[
                styles.button,
                this.state.pressed ? { backgroundColor: "green" } : {}
            ]}
            onHideUnderlay={() => {
                this.setState({ pressed: false });
            }}
            onShowUnderlay={() => {
                this.setState({ pressed: true });
            }}
        >
            <Text>Button</Text>
        </TouchableHighlight>
    );
}
}

const styles = StyleSheet.create({
button: {
    padding: 10,
    borderColor: "blue",
    borderWidth: 1,
    borderRadius: 5
}
});

0
使用类似这样的代码:
class A extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      onClicked: false
    }
    this.handlerButtonOnClick = this.handlerButtonOnClick.bind(this);
  }
  handlerButtonOnClick(){
    this.setState({
       onClicked: true
    });
  }
  render() {
    var _style;
    if (this.state.onClicked){ // clicked button style
      _style = {
          color: "red"
        }
    }
    else{ // default button style
      _style = {
          color: "blue"
        }
    }
    return (
        <div>
            <button
                onClick={this.handlerButtonOnClick}
                style={_style}>Press me !</button>
        </div>
    );
  }
}

如果您使用外部CSS,可以使用className代替style属性:

render() {
    var _class = "button";
    var _class.concat(this.state.onClicked ? "-pressed" : "-normal") ;
    return (
        <div>
            <button
                onClick={this.handlerButtonOnClick}
                className={_class}>Press me !</button>
        </div>
    );
  }

如何应用 CSS 并不重要。请关注 "handlerButtonOnClick" 方法。

当状态改变时,组件会重新渲染("render" 方法会再次调用)。

祝好运 ;)


React Native 没有按钮组件。它使用 touchableHighlight、touchableNativeFeedback 等其他组件。 - Nico
问题不在于使用React Native与否,而在于理解React何时以及如何对组件应用样式。 流程始终如一:处理事件 -> 处理程序 -> 设置状态 -> 渲染。 我的回答涉及此流程,而非React Native。 - sami ghazouane
1
更新 - React Native在版本0.37中添加了<Button />组件。 - Hastig Zusammenstellen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接