首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当PanResponder在Animated.View孩提时代有Animated.ScrollView时,Animated.ScrollView在安卓上不能正常工作

当PanResponder在Animated.View孩提时代有Animated.ScrollView时,Animated.ScrollView在安卓上不能正常工作
EN

Stack Overflow用户
提问于 2019-05-01 16:28:37
回答 1查看 1.2K关注 0票数 3

我在Android上有个问题。

我的Animated.View里面有一个Animated.View。每当我缓慢地拖动我的Animated.View时,它就工作得很好,但是每当我快速地弹出时,Animated.View就会在几个像素之后停止。

当我禁用Animated.ScrollView上的滚动时,错误不会发生。我的猜测是,Animated.ScrollView接管时,刷卡太快。

有人知道为什么会发生这种事吗?这种情况在iOS上不会发生。

详细视图:

代码语言:javascript
复制
class DetailScreen extends PureComponent<Props> {
    state = {
        closeToTop: true,
        closeToBottom: false
    };

    scrollY = new Animated.Value(0);
    scrollView?: ScrollView;

    handleScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
        const closeToTop = this.isCloseToTop(e);
        if (closeToTop !== this.state.closeToTop) {
            this.setState({ closeToTop });
        }

        const closeToBottom = this.isCloseToBottom(e);
        if (closeToBottom !== this.state.closeToBottom) {
            this.setState({ closeToBottom });
        }
    };

    isCloseToTop = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
        const { contentOffset } = e.nativeEvent;

        return contentOffset.y === 0;
    };

    isCloseToBottom = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
        const { layoutMeasurement, contentOffset, contentSize } = e.nativeEvent;
        return layoutMeasurement.height + contentOffset.y >= contentSize.height - 20;
    };

    renderContent = () => {
        return (
            <Animated.ScrollView
                contentContainerStyle={{ flexGrow: 1 }}
                scrollEventThrottle={16}
                bounces={false}
                // scrollEnabled={false}
                overScrollMode={"never"}
                onScroll={Animated.event(
                    [
                        {
                            nativeEvent: {
                                contentOffset: {
                                    y: this.scrollY
                                }
                            }
                        }
                    ],
                    {
                        useNativeDriver: true,
                        listener: this.handleScroll
                    }
                )}
                ref={(ref: any) => (this.scrollView = ref && ref.getNode())}>
                <TouchableWithoutFeedback>
                    <View style={{flex: 1}}>
                        <View style={{...styles.container, height: 200, backgroundColor: "red"}}>
                            <Text>red</Text>
                        </View>
                        <View style={{ ...styles.container, height: 200, backgroundColor: "yellow" }}>
                            <Text>yellow</Text>
                        </View>
                        <View style={{ ...styles.container, height: 200, backgroundColor: "green" }}>
                            <Text>green</Text>
                        </View>
                        <View style={{ ...styles.container, height: 200, backgroundColor: "blue" }}>
                            <Text>blue</Text>
                        </View>
                        <View style={{ ...styles.container, height: 200, backgroundColor: "red" }}>
                            <Text>red</Text>
                        </View>
                        <View style={{ ...styles.container, height: 200, backgroundColor: "yellow" }}>
                            <Text>yellow</Text>
                        </View>
                    </View>
                </TouchableWithoutFeedback>
            </Animated.ScrollView>
        );
    };

    render() {
        return (
                <SwipeableModal
                    onClose={this.props.navigation.pop}
                    nearTop={this.state.closeToTop}
                    nearBottom={this.state.closeToBottom}>
                    {this.renderContent()}
                </SwipeableModal>
        );
    }
 }

可滑动模态

代码语言:javascript
复制
const { height: screenHeight } = Dimensions.get("window");
const TIMING_CONFIG = { duration: 300, easing: Easing.inOut(Easing.ease) };

class SwipeableModal extends PureComponent<Props, State> {
    panResponder: PanResponderInstance;

    constructor(props: Props) {
        super(props);
        this.state = {
            pan: new Animated.ValueXY({ x: 0, y: 0 }),
            isDragging: false
        };

        this.panResponder = PanResponder.create({
            // Ask to be the responder:
            onStartShouldSetPanResponder: () => false,
            onStartShouldSetPanResponderCapture: () => false,
            onMoveShouldSetPanResponderCapture: () => false,
            onPanResponderTerminationRequest: () => false,

            onMoveShouldSetPanResponder: (evt, gestureState) => {
                if (this.state.isDragging) {
                    return true;
                }

                // moving finger from top to bottom
                if (gestureState.vy > 0 && this.props.nearTop) {
                    this.setState({ isDragging: true });
                    return true;
                }

                // moving finger from bottom to top
                if (gestureState.vy < 0 && this.props.nearBottom) {
                    this.setState({ isDragging: true });
                    return true;
                }

                return false;
            },
            onPanResponderMove: (evt, gestureState) => {
                this.state.pan.setValue({ x: 0, y: gestureState.dy });
            },
            onPanResponderRelease: (evt, gestureState) => {
                this.setState({ isDragging: false });
                if (gestureState.vy <= -0.7 || gestureState.dy <= -300) {
                    // move from bottom to top
                    Animated.timing(this.state.pan, {
                        toValue: { x: 0, y: -screenHeight },
                        ...TIMING_CONFIG
                    }).start(this.closeModal);
                } else if (gestureState.vy >= 0.5 || gestureState.dy >= 300) {
                    // move from top to
                    Animated.timing(this.state.pan, {
                        toValue: { x: 0, y: screenHeight },
                        ...TIMING_CONFIG
                    }).start(this.closeModal);
                } else {
                    Animated.spring(this.state.pan, {
                        toValue: 0
                    }).start();
                }
            }
        });
    }

    closeModal = () => {
        this.props.onClose();
    };

    handleGetStyle() {
        return [
            style.container,
            {
                transform: [...this.state.pan.getTranslateTransform()]
            }
        ];
    }

    render() {
        return (
            <Animated.View style={this.handleGetStyle()} {...this.panResponder.panHandlers}>
                {this.props.children}
            </Animated.View>
        );
    }
}

视频示例 复制错误的Github项目

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-24 09:24:17

对于那些想知道的人,我能够通过使用react本机手势处理程序重新实现可滑动模式来解决这个问题。

如果有人需要帮助,请告诉我。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55939409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档