discussions-and-proposals icon indicating copy to clipboard operation
discussions-and-proposals copied to clipboard

PanResponder goes out of view

Open NamrataDwivedi opened this issue 3 years ago • 0 comments

Discussed in https://github.com/react-native-community/discussions-and-proposals/discussions/427

Originally posted by NamrataDwivedi November 16, 2021 I have a requirement to make a section swipeable in left and right only. There are 3 views in my Class Component. Example

In the above image I have applied the PanResponder to Red box, but the effect is happening in whole Green portion of the UI.

`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 && 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>
                    </View>
                </Animated.View>
                </View>
            )
        }
    }).reverse();
}

}

Above code is for the red box. I am just rendering this UI in another Component class.

My requirement is to just make the red box items swipeable in left and right.

Help would be appreciated.

NamrataDwivedi avatar Nov 16 '21 09:11 NamrataDwivedi