React Native Flip Card 无法在翻盖上工作
React Native Flip Card not Working on flip
我正在尝试制作翻转纸牌游戏。我将 GestureFlipView 用于翻转卡片动画。我想在 3X3 网格中显示这些翻盖卡片,为此我使用了 React Native。但是问题出现了,卡片没有被翻转,而且它也表现出模糊的行为。只有最后一张卡工作正常,其他卡的行为不可预测。
Github 回购:https://github.com/akhilomar/React-Native-Number-Game
卡片屏幕:https://i.stack.imgur.com/Cliww.png
卡片组件
import {View, Text, SafeAreaView, TouchableOpacity} from 'react-native';
import GestureFlipView from 'react-native-gesture-flip-card';
const Cards = (props) => {
const [flipType, setFlip] = useState('left');
useEffect(() => {
})
const renderFront = () => {
return(
<TouchableOpacity onPress = {() => {
this.flipView.flipRight()
setFlip('right');
console.log("Pressed" + `${props.val}`)
}} >
<View style = {{backgroundColor:'red', width: 100, height: 100, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: "white", fontSize: 20}}>Swipe Me</Text>
</View>
</TouchableOpacity>
);
};
const renderBack = () => {
return(
<View style = {{backgroundColor:'blue', width: 100, height: 100, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: "white", fontSize: 30}}>{props.val}</Text>
{/* <TouchableOpacity onPress = {() => {
(flipType === 'left') ? this.flipView.flipRight() : this.flipView.flipLeft();
setFlip((flipType === 'left') ? 'right' : 'left');
}} style = {{padding: 10, backgroundColor: 'purple', width: 100, height: 40, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: 'white'}}>Reverse</Text>
</TouchableOpacity> */}
</View>
);
};
//ref = {(ref) => this.flipView = ref}
return(
<SafeAreaView style = {{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<GestureFlipView ref = {(ref) => this.flipView = ref} width={300} height = {500}>
{renderFront()}
{renderBack()}
</GestureFlipView>
</SafeAreaView>
);
}
export default Cards;```
**Card List Component**
```import React from 'react';
import {SafeAreaView, View, FlatList, Dimensions, StyleSheet } from 'react-native';
import Cards from './Cards';
const CardScreen = () => {
// const data = ['1','2','3','4','5','6','7','8','9'];
const DATA = [
{
id: '1',
title: '1',
},
{
id: '2',
title: '2',
},
{
id: '3',
title: '3',
},
{
id: '4',
title: '4',
},
{
id: '5',
title: '5',
},
{
id: '6',
title: '6',
},
{
id: '7',
title: '7',
},
{
id: '8',
title: '8',
},
{
id: '9',
title: '9',
}
];
const Shuffle = (arr1) => {
var ctr = arr1.length, temp, index;
while (ctr > 0) {
index = Math.floor(Math.random() * ctr);
ctr--;
temp = arr1[ctr];
arr1[ctr] = arr1[index];
arr1[index] = temp;
}
return arr1;
}
const numColumns = 3;
const size = Dimensions.get('window').width/numColumns;
const styles = StyleSheet.create({
itemContainer: {
width: size,
height: size,
},
item: {
flex: 1,
margin: 3,
backgroundColor: 'lightblue',
}
});
return(
<>
<FlatList
data={DATA}
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<Cards val = {item.value}/>
</View>
)}
keyExtractor={item => item.id}
numColumns={numColumns} />
{/* {
data.map((index, item) => {
return(
<View style={styles.itemContainer}>
<Cards val = {item}/>
</View>
);
})
} */}
</>
);
}
export default CardScreen;```
您需要正确使用ref
。你可以阅读它 here
const Cards = (props) => {
//first define ref
const flipViewRef = React.useRef();
//in onPress use it like this
<TouchableOpacity onPress = {() => {
flipViewRef.current.flipRight()
...
}} >
//in GestureFlipView assign it like this
<GestureFlipView ref={flipViewRef} />
}
您遇到麻烦的主要原因是您在功能组件中使用了 this
引用。正如所解释的 here, the value of this
will be determined by how the function is called, and might even be undefined
. A more reliable approach of using this
is from a class context. For React, that means using a class component, rather than a functional component, which is what is being used here. You can read about function and class components here.
还需要考虑的是 FlatList
在这里是否合适。通常,此组件用于 improve performance 呈现大型列表。与其使用 FlatList
,我建议使用更简单的东西,例如一组 View
组件来抽牌。这是一个基于您的代码的完整示例:
import React, { useState } from 'react';
import { View, Dimensions, StyleSheet, Text, TouchableOpacity } from 'react-native';
import GestureFlipView from 'react-native-gesture-flip-card';
const Card = (props: any) => {
const [flipType, setFlip] = useState('left');
let flipView: any;
const onFrontPress = () => {
flipView.flipRight()
setFlip('right');
}
const cardDimensions = { width: 0.9 * props.size, height: 0.9 * props.size };
const renderFront = () => {
return (
<TouchableOpacity onPress={onFrontPress} style={[styles.front, cardDimensions]}>
<Text style={styles.frontText}>Swipe Me</Text>
</TouchableOpacity>
);
};
const renderBack = () => {
return (
<View style={[styles.back, cardDimensions]}>
<Text style={styles.backText}>{props.val}</Text>
</View>
);
};
return (
<GestureFlipView ref={(ref) => flipView = ref} width={props.size} height={props.size}>
{renderFront()}
{renderBack()}
</GestureFlipView>
);
}
const CardRow = () => {
const size = Dimensions.get('window').width / 3;
return (
<View style={styles.rowContainer}>
<Card size={size} />
<Card size={size} /{ width: 0.9 * props.size, height: 0.9 * props.size }>
<Card size={size} />
</View>
);
}
const CardScreen = () => {
return (
<View style={styles.container}>
<CardRow />
<CardRow />
<CardRow />
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1,
},
rowContainer: {
flexDirection: 'row',
justifyContent: 'space-evenly',
},
back: {
backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'center'
},
backText: {
color: "white",
fontSize: 30
},
front: {
backgroundColor: 'green',
alignItems: 'center',
justifyContent: 'center',
},
frontText: {
color: "white",
fontSize: 20
}
});
export default CardScreen;
我正在尝试制作翻转纸牌游戏。我将 GestureFlipView 用于翻转卡片动画。我想在 3X3 网格中显示这些翻盖卡片,为此我使用了 React Native。但是问题出现了,卡片没有被翻转,而且它也表现出模糊的行为。只有最后一张卡工作正常,其他卡的行为不可预测。
Github 回购:https://github.com/akhilomar/React-Native-Number-Game
卡片屏幕:https://i.stack.imgur.com/Cliww.png
卡片组件
import {View, Text, SafeAreaView, TouchableOpacity} from 'react-native';
import GestureFlipView from 'react-native-gesture-flip-card';
const Cards = (props) => {
const [flipType, setFlip] = useState('left');
useEffect(() => {
})
const renderFront = () => {
return(
<TouchableOpacity onPress = {() => {
this.flipView.flipRight()
setFlip('right');
console.log("Pressed" + `${props.val}`)
}} >
<View style = {{backgroundColor:'red', width: 100, height: 100, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: "white", fontSize: 20}}>Swipe Me</Text>
</View>
</TouchableOpacity>
);
};
const renderBack = () => {
return(
<View style = {{backgroundColor:'blue', width: 100, height: 100, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: "white", fontSize: 30}}>{props.val}</Text>
{/* <TouchableOpacity onPress = {() => {
(flipType === 'left') ? this.flipView.flipRight() : this.flipView.flipLeft();
setFlip((flipType === 'left') ? 'right' : 'left');
}} style = {{padding: 10, backgroundColor: 'purple', width: 100, height: 40, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: 'white'}}>Reverse</Text>
</TouchableOpacity> */}
</View>
);
};
//ref = {(ref) => this.flipView = ref}
return(
<SafeAreaView style = {{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<GestureFlipView ref = {(ref) => this.flipView = ref} width={300} height = {500}>
{renderFront()}
{renderBack()}
</GestureFlipView>
</SafeAreaView>
);
}
export default Cards;```
**Card List Component**
```import React from 'react';
import {SafeAreaView, View, FlatList, Dimensions, StyleSheet } from 'react-native';
import Cards from './Cards';
const CardScreen = () => {
// const data = ['1','2','3','4','5','6','7','8','9'];
const DATA = [
{
id: '1',
title: '1',
},
{
id: '2',
title: '2',
},
{
id: '3',
title: '3',
},
{
id: '4',
title: '4',
},
{
id: '5',
title: '5',
},
{
id: '6',
title: '6',
},
{
id: '7',
title: '7',
},
{
id: '8',
title: '8',
},
{
id: '9',
title: '9',
}
];
const Shuffle = (arr1) => {
var ctr = arr1.length, temp, index;
while (ctr > 0) {
index = Math.floor(Math.random() * ctr);
ctr--;
temp = arr1[ctr];
arr1[ctr] = arr1[index];
arr1[index] = temp;
}
return arr1;
}
const numColumns = 3;
const size = Dimensions.get('window').width/numColumns;
const styles = StyleSheet.create({
itemContainer: {
width: size,
height: size,
},
item: {
flex: 1,
margin: 3,
backgroundColor: 'lightblue',
}
});
return(
<>
<FlatList
data={DATA}
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<Cards val = {item.value}/>
</View>
)}
keyExtractor={item => item.id}
numColumns={numColumns} />
{/* {
data.map((index, item) => {
return(
<View style={styles.itemContainer}>
<Cards val = {item}/>
</View>
);
})
} */}
</>
);
}
export default CardScreen;```
您需要正确使用ref
。你可以阅读它 here
const Cards = (props) => {
//first define ref
const flipViewRef = React.useRef();
//in onPress use it like this
<TouchableOpacity onPress = {() => {
flipViewRef.current.flipRight()
...
}} >
//in GestureFlipView assign it like this
<GestureFlipView ref={flipViewRef} />
}
您遇到麻烦的主要原因是您在功能组件中使用了 this
引用。正如所解释的 here, the value of this
will be determined by how the function is called, and might even be undefined
. A more reliable approach of using this
is from a class context. For React, that means using a class component, rather than a functional component, which is what is being used here. You can read about function and class components here.
还需要考虑的是 FlatList
在这里是否合适。通常,此组件用于 improve performance 呈现大型列表。与其使用 FlatList
,我建议使用更简单的东西,例如一组 View
组件来抽牌。这是一个基于您的代码的完整示例:
import React, { useState } from 'react';
import { View, Dimensions, StyleSheet, Text, TouchableOpacity } from 'react-native';
import GestureFlipView from 'react-native-gesture-flip-card';
const Card = (props: any) => {
const [flipType, setFlip] = useState('left');
let flipView: any;
const onFrontPress = () => {
flipView.flipRight()
setFlip('right');
}
const cardDimensions = { width: 0.9 * props.size, height: 0.9 * props.size };
const renderFront = () => {
return (
<TouchableOpacity onPress={onFrontPress} style={[styles.front, cardDimensions]}>
<Text style={styles.frontText}>Swipe Me</Text>
</TouchableOpacity>
);
};
const renderBack = () => {
return (
<View style={[styles.back, cardDimensions]}>
<Text style={styles.backText}>{props.val}</Text>
</View>
);
};
return (
<GestureFlipView ref={(ref) => flipView = ref} width={props.size} height={props.size}>
{renderFront()}
{renderBack()}
</GestureFlipView>
);
}
const CardRow = () => {
const size = Dimensions.get('window').width / 3;
return (
<View style={styles.rowContainer}>
<Card size={size} />
<Card size={size} /{ width: 0.9 * props.size, height: 0.9 * props.size }>
<Card size={size} />
</View>
);
}
const CardScreen = () => {
return (
<View style={styles.container}>
<CardRow />
<CardRow />
<CardRow />
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1,
},
rowContainer: {
flexDirection: 'row',
justifyContent: 'space-evenly',
},
back: {
backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'center'
},
backText: {
color: "white",
fontSize: 30
},
front: {
backgroundColor: 'green',
alignItems: 'center',
justifyContent: 'center',
},
frontText: {
color: "white",
fontSize: 20
}
});
export default CardScreen;