我正在进行测验。并且所有选项都将呈现为循环。
预期行为:
当我点击某个选项时,如果是错误的答案,则应将背景颜色更改为红色并且应该摇动。
以下是我正在尝试的代码。
import React, { Component } from "react";
import {
View,
Text,
TouchableWithoutFeedback,
Animated,
Easing
} from "react-native";
class MCQOptions extends Component {
state = {
optionSelectedStatus: 0 // 0: unselected, 1: correct, -1: wrong
};
constructor() {
super();
this.animatedValue = new Animated.Value(0);
this.shakeAnimValue = new Animated.Value(0);
}
onOptionSelected(i) {
// this.props.showNextQuestion();
var answer = this.props.answer;
if (answer == i) {
this.setState({ optionSelectedStatus: 1 });
this.showCorrectAnimation();
} else {
this.setState({ optionSelectedStatus: -1 });
this.showErrorAnimation();
}
}
showErrorAnimation() {
this.shakeAnimValue.setValue(0);
Animated.timing(this.shakeAnimValue, {
toValue: 1,
duration: 300,
easing: Easing.linear
}).start();
}
showCorrectAnimation() {}
getOptions() {
var options = [];
var optionSelectedStyle = styles.optionUnselected;
var optionShadowStyle = styles.optionShadow;
if (this.state.optionSelectedStatus == 1) {
optionSelectedStyle = styles.optionCorrect;
optionShadowStyle = null;
} else if (this.state.optionSelectedStatus == -1) {
optionSelectedStyle = styles.optionWrong;
optionShadowStyle = null;
}
const marginLeft = this.shakeAnimValue.interpolate({
inputRange: [0, 0.2, 0.4, 0.6, 0.8, 0.9, 1],
outputRange: [0, -10, 10, -10, 10, -10, 0]
});
for (var i = 0; i < this.props.options.length; i++) {
options.push(
<TouchableWithoutFeedback
onPress={this.onOptionSelected.bind(this, this.props.indexes[i])}
key={"options_" + i}
>
<View style={styles.optionBox}>
<View style={optionShadowStyle} />
<Animated.Text
style={[
styles.option,
optionSelectedStyle,
{ marginLeft: marginLeft }
]}
key={"option" + i}
>
{this.props.options[i]}
</Animated.Text>
</View>
</TouchableWithoutFeedback>
);
}
return options;
}
render() {
const marginTop = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [100, 0]
});
const opacity = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1]
});
return (
<Animated.View style={{ marginTop: marginTop, opacity: opacity }}>
{this.getOptions()}
</Animated.View>
);
}
// Animations
componentDidMount() {
this.slideUpOptionsContainer();
}
componentWillReceiveProps() {
this.slideUpOptionsContainer();
this.setState({ optionSelectedStatus: 0 });
}
slideUpOptionsContainer() {
this.animatedValue.setValue(0);
Animated.timing(this.animatedValue, {
toValue: 1,
duration: 300,
easing: Easing.linear
}).start();
}
}
const styles = {
optionBox: {
margin: 5
},
optionsContainer: {
marginTop: 100
},
option: {
padding: 10,
textAlign: "center",
borderRadius: 10,
overflow: "hidden",
width: "100%"
},
optionUnselected: {
backgroundColor: "#FFF"
},
optionWrong: {
backgroundColor: "red"
},
optionCorrect: {
backgroundColor: "green"
},
optionShadow: {
backgroundColor: "rgba(255,255,255,0.85)",
position: "absolute",
width: "100%",
height: "100%",
left: -5,
top: 5,
borderRadius: 10
}
};
export default MCQOptions;
上面的代码动画(摇动)所有选项(根据写入的登录信息是正确的),我被困在如何只让点击的选项变得动画而不是全部?
编辑:
使用道具Feed的父组件:
class MCQ extends Component<{}> {
render() {
var options = ["yes", "no", "can't define"];
var indexes = [1,2,3];
var answer = 1;
optionsObj = <MCQOptions
options={options}
indexes={indexes}
answer={answer}/>;
return (
<View style={styles.container} >
<View style={styles.optionsContainer}>
{optionsObj}
</View>
</View>
);
}
}
const styles = {
container: {
flex: 1,
backgroundColor: "blue",
paddingTop: 20,
justifyContent: 'flex-start',
padding: 20
},
};
export default MCQ;
第二次编辑: 尝试简化问题。
以下是零道具的简化代码。我想仅为点击元素设置动画。
import React, { Component } from "react";
import {
View,
Text,
TouchableWithoutFeedback,
Animated,
Easing
} from "react-native";
class MCQOptions extends Component {
constructor() {
super();
this.shakeAnimValue = new Animated.Value(0);
}
showErrorAnimation() {
this.shakeAnimValue.setValue(0);
Animated.timing(this.shakeAnimValue, {
toValue: 1,
duration: 300,
easing: Easing.linear
}).start();
}
getOptions() {
const marginLeft = this.shakeAnimValue.interpolate({
inputRange: [0, 0.2, 0.4, 0.6, 0.8, 0.9, 1],
outputRange: [0, -10, 10, -10, 10, -10, 0]
});
var options = [];
for (var i = 0; i < 4; i++) {
options.push(
<TouchableWithoutFeedback
onPress={this.showErrorAnimation.bind(this)}
key={"options_" + i}
>
<View style={styles.optionBox}>
<Animated.Text style={[
styles.option,
{ marginLeft: marginLeft }
]}
key={"option" + i}
>
{"Option "+i}
</Animated.Text>
</View>
</TouchableWithoutFeedback>
);
}
return options;
}
render() {
return (
<View style={{ marginTop: 100}}>
{this.getOptions()}
</View>
);
}
}
const styles = {
optionBox: {
margin: 5
},
optionsContainer: {
marginTop: 100
},
option: {
padding: 10,
textAlign: "center",
borderRadius: 10,
overflow: "hidden",
width: "100%"
},
optionUnselected: {
backgroundColor: "#FFF"
},
optionWrong: {
backgroundColor: "red"
},
};
export default MCQOptions;
答案 0 :(得分:4)
由于您希望单独为它们设置动画,因此它们无法绑定到同一个Animated
对象。你必须使它们成倍,例如:
示例:强>
export class App extends Component {
constructor() {
super();
this.getOptions = this.getOptions.bind(this);
this.originalOptions = [0,1,2,3];
this.shakeAnimations = this.originalOptions.map( (i) => new Animated.Value(0) );
}
showErrorAnimation(i) {
this.shakeAnimations[i].setValue(0);
Animated.timing(this.shakeAnimations[i], {
toValue: 1,
duration: 300,
easing: Easing.linear
}).start();
}
getOptions() {
var options = this.originalOptions.map( (i) => {
const marginLeft = this.shakeAnimations[i].interpolate({
inputRange: [0, 0.2, 0.4, 0.6, 0.8, 0.9, 1],
outputRange: [0, -10, 10, -10, 10, -10, 0]
});
return (
<TouchableWithoutFeedback
onPress={() => this.showErrorAnimation(i)}
key={"options_" + i}
>
<View style={styles.optionBox}>
<Animated.Text style={[
styles.option,
{ marginLeft: marginLeft }
]}
key={"option" + i}
>
{"Option "+i}
</Animated.Text>
</View>
</TouchableWithoutFeedback>
)
});
return options;
}
render() {
return (
<View style={{ marginTop: 100}}>
{this.getOptions()}
</View>
);
}
}
const styles = {
optionBox: {
margin: 5
},
optionsContainer: {
marginTop: 100
},
option: {
padding: 10,
textAlign: "center",
borderRadius: 10,
overflow: "hidden",
width: "100%"
},
optionUnselected: {
backgroundColor: "#FFF"
},
optionWrong: {
backgroundColor: "red"
},
};
<强>结果:强>