#reactjs #react-native #animation #gesture #panresponder
Вопрос:
У меня есть требование, чтобы раздел можно было пролистывать только слева и справа. В моем компоненте класса есть 3 представления. введите описание изображения здесь
На приведенном выше изображении я применил PanResponder к красному окну, но эффект наблюдается во всей зеленой части пользовательского интерфейса.
import React, { Component } from 'react';
import { StyleSheet, Text, View, Animated, Dimensions, PanResponder } from 'react-native';
import { connect } from "react-redux";
import CardError from '../../../assets/SVG/bankerror.svg';
import RightPolygon from "../../../assets/SVG/RightPolygon.svg";
import { FONT_FAMILY } from "@utils";
const SCREEN_HEIGHT = 140
const SCREEN_WIDTH = Dimensions.get('window').width
import React, { Component } from 'react';
import { StyleSheet, Text, View, Animated, Dimensions, PanResponder } from 'react-native';
import { connect } from "react-redux";
import CardError from '../../../assets/SVG/bankerror.svg';
import RightPolygon from "../../../assets/SVG/RightPolygon.svg";
import { FONT_FAMILY } from "@utils";
const SCREEN_HEIGHT = 140
const SCREEN_WIDTH = Dimensions.get('window').width
class TwitterSwipe extends Component {
constructor(props) {
super(props)
this.position = new Animated.ValueXY();
this.rotate = this.position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: ['-30deg', '0deg', '10deg'],
extrapolate: 'clamp'
})
this.rotateAndTranslate = {
transform: [{
rotate: this.rotate
},
...this.position.getTranslateTransform()
]
}
this.state = {
currentIndex: 0,
listOfBanks: [
{
"title": "Title 1",
"description": " Description 1"
},
{
"title": "Title 2",
"description": " Description 2"
},
{
"title": "Title 3",
"description": " Description 3"
}
]
}
}
UNSAFE_componentWillMount() {
this.PanResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderMove: (evt, gestureState) => {
},
onPanResponderRelease: (evt, gestureState) => {
console.log(evt)
if (gestureState.moveX == 0 amp;amp; gestureState.moveY == 0) {
alert("clicked");
} else if (gestureState.dx > 120) {
Animated.spring(this.position, {
toValue: { x: SCREEN_WIDTH 50, y: gestureState.dy }
}).start(() => {
this.setState({ currentIndex: this.state.currentIndex 1 }, () => {
this.position.setValue({ x: 0, y: 0 })
})
})
}
else if (gestureState.dx < -120) {
Animated.spring(this.position, {
toValue: { x: -SCREEN_WIDTH - 50, y: gestureState.dy }
}).start(() => {
this.setState({ currentIndex: this.state.currentIndex 1 }, () => {
this.position.setValue({ x: 0, y: 0 })
})
})
}
else {
Animated.spring(this.position, {
toValue: { x: 0, y: 0 },
friction: 4
}).start()
}
},
})
}
render() {
return (
<View style={{ height: this.state.currentIndex == this.state.listOfBanks.length ? 0 : 140 ,
marginBottom : this.state.currentIndex == this.state.listOfBanks.length ? 0 : 20
}}>
{this.renderCard()}
</View>
);
}
renderCard = () => {
return this.state.listOfBanks.map((item, i) => {
if (i < this.state.currentIndex) {
return null;
} else if (i == this.state.currentIndex) {
return (
<View>
<Animated.View
{...this.PanResponder.panHandlers}
key={i}
style={[
this.rotateAndTranslate,
{
height: SCREEN_HEIGHT,
width: "100%",
padding: 10,
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
marginTop: i * 5,
justifyContent: 'center',
alignItems: 'center'
}
]}
>
<View style={styles.mainContainerStyle}>
<View
style={{ flexDirection: "row" }}>
<View style={{ flex: 0.5 }}>
<CardError
height={24}
width={24}
/>
</View>
<View style={{
flex: 9, flexDirection: "column", marginStart: 20,
}}>
<Text
style={{
fontSize: 15,
fontWeight: "500",
lineHeight: 16,
color: "#1D1E1F",
fontFamily: FONT_FAMILY.SFProText,
}}
>{item.title}</Text>
<Text
style={{
fontSize: 13,
fontWeight: "400",
lineHeight: 16,
color: "#91919F",
fontFamily: FONT_FAMILY.SFProText,
marginTop: 10
}}
>{item.description} </Text>
</View>
<View style={{ flex: 0.5 }} >
<RightPolygon
height={15}
width={15}
style={{ marginRight: 3 }}
/>
</View>
</View>
</View>
</Animated.View>
</View>
)
} else {
return (
<View>
<Animated.View
key={i}
style={[
{
height: SCREEN_HEIGHT,
width: "100%",
padding: 10,
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
marginTop: i * 5,
justifyContent: 'center',
alignItems: 'center'
}
]}
>
<View style={styles.mainContainerStyle}>
<View
style={{ flexDirection: "row" }}>
<View style={{ flex: 0.5 }}>
<CardError
height={24}
width={24}
/>
</View>
<View style={{
flex: 9, flexDirection: "column", marginStart: 20,
}}>
<Text
style={{
fontSize: 15,
fontWeight: "500",
lineHeight: 16,
color: "#1D1E1F",
fontFamily: FONT_FAMILY.SFProText,
}}
>{item.title}</Text>
<Text
style={{
fontSize: 13,
fontWeight: "400",
lineHeight: 16,
color: "#91919F",
fontFamily: FONT_FAMILY.SFProText,
marginTop: 10
}}
>{item.description} </Text>
</View>
{/* <View style={{ flex: 0.5 }} >
<AnimatedPressable onPress={() => alert('test onPress')}>
<RightPolygon
height={15}
width={15}
style={{ marginRight: 3 }}
/>
</AnimatedPressable>
</View> */}
</View>
</View>
</Animated.View>
</View>
)
}
}).reverse();
}
}
const mapStateToProps = state => {
return {
reduxUserData: state.userData.userData,
};
};
const mapDispatchToProps = dispatch => {
};
const styles = StyleSheet.create({
mainContainerStyle: {
backgroundColor: "#FFF",
marginTop: 20,
width: "100%",
alignSelf: "center",
elevation: 10,
paddingVertical: 15,
borderRadius: 15,
shadowColor: "grey",
shadowOffset: { width: 0, height: 0 },
shadowRadius: 1,
shadowOpacity: 1,
height: 100,
padding: 20,
flex: 1,
}
})
export default connect(mapStateToProps, mapDispatchToProps)(TwitterSwipe);
Приведенный выше код предназначен для красного ящика. Я просто визуализирую этот пользовательский интерфейс в другом классе компонентов.
Мое требование состоит в том, чтобы просто сделать элементы в красном поле доступными для перемещения влево и вправо.
Помощь была бы признательна.