首页 > 解决方案 > React Native - PanGestureHandler 在更改组件状态后不起作用

问题描述

我有两个屏幕,1)视频通话屏幕 2)聊天屏幕。

我已经使用库https://github.com/kevinstumpf/react-native-flip-view实现了翻转视图,将视频通话屏幕显示为前屏,当有人点击聊天时,翻转视图并将聊天显示为后屏.

我想在带有可拖动视图的聊天和视频通话屏幕中显示缩略图摄像头视图,它在第一次加载时工作,但是当我翻转屏幕时,PanGestureHandler 停止工作,尽管我可以看到摄像头缩略图视图在屏幕上仍然可见翻转后,它的位置被重置为左上角(初始位置)并且拖动不再起作用。

下面是我正在使用的代码。

import React, { Component } from 'react';
import { View, SafeAreaView, Dimensions, TouchableOpacity, Easing } from 'react-native';
import { moderateScale } from 'react-native-size-matters';
import { PanGestureHandler, State } from 'react-native-gesture-handler';
import { onGestureEvent } from 'react-native-redash';
import FlipView from 'react-native-flip-view-next';
import Animated from 'react-native-reanimated'
import ChatScreen from './../screens/ChatScreen';

const { Value, diffClamp, cond, set, eq, add } = Animated;
const DEVICE_WIDTH = Dimensions.get('window').width;
const DEVICE_HEIGHT = Dimensions.get('window').height;
const CARDWIDTH = moderateScale(120);
const CARDHEIGHT = moderateScale(160);
const withOffset = (value: Animated.Value<number>, state: Animated.Value<State>) => {
    const offset = new Value(0)
    return cond(eq(state, State.END), [set (offset, add(offset, value)), offset], add(offset, value));
};

export default class VideoSessionScreen extends Component {

    state = {
        isFlipped: false,
        ...
    }

    renderCameraThumbView = () => {
        const state = new Value(-1);
        const translationX = new Value(0);
        const translationY = new Value(0);
        const gestureHandler = onGestureEvent({state, translationX, translationY});
        const translateX = diffClamp(withOffset(translationX, state), 0, DEVICE_WIDTH-CARDWIDTH-moderateScale(30));
        const translateY = diffClamp(withOffset(translationY, state), 0, DEVICE_HEIGHT-CARDHEIGHT-moderateScale(55));
        return (
            <PanGestureHandler {...gestureHandler}>
                <Animated.View style={{ transform: [{translateX}, {translateY}], borderRadius: moderateScale(15), height: CARDHEIGHT, width: CARDWIDTH, overflow: 'hidden'}}>
                    {!this.state.isFlipped &&
                        <CameraLocalView enabled={true} style={{flex: 1}}/>
                    }
                    {this.state.isFlipped &&
                        <View style={{flex: 1, backgroundColor: '#111111'}}>
                            {Array.from(this.state.videoTracks, ([sid, trackId]) => {
                                return (
                                    <CameraRemoteView/>
                                )
                            })}
                        </View>
                    }
                </Animated.View>
            </PanGestureHandler>
        );
    };

    _renderFront() {
        return(
            <SafeAreaView style={{flex: 1, backgroundColor: '#111'}}>
                {'local' === this.state.cameraView &&
                    <>
                        <View style={{position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, backgroundColor: 'red'}}>

                        </View>
                        <Animated.View style={{position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, padding: moderateScale(15)}}>
                            {this.renderCameraThumbView()}
                        </Animated.View>
                    </>
                }
            </SafeAreaView>
        );
    }

    _renderBack() {
        return(
            <View style={{flex: 1}}>
                <ChatScreen
                    didPressBackBtn = {() => {
                        this.setState({
                            isFlipped: false
                        })
                    }}
                />
            </View>
        )
    }

    render() {
        return (
            <>
                <FlipView style={{flex: 1}}
                    front={this._renderFront()}
                    back={this._renderBack()}
                    isFlipped={this.state.isFlipped}
                    flipAxis="y"
                    flipEasing={Easing.out(Easing.ease)}
                    flipDuration={500}
                    perspective={1000}
                />
            </>
        );
    }
}

我打电话后 PanGestureHandler 不起作用的可能原因是什么,this.state({{isFlipped: !this.state.isFlipped}})我该如何解决这个问题?

谢谢。

标签: react-native

解决方案


我不得不重做并按照以下方式实现它,现在效果很好。

import React, { Component } from 'react';
import { moderateScale } from 'react-native-size-matters';
import { PanGestureHandler, State } from 'react-native-gesture-handler';
import Animated from 'react-native-reanimated'

const { cond, eq, add, set, Value, event } = Animated;
const CARDWIDTH = moderateScale(120);
const CARDHEIGHT = moderateScale(160);

export default class VideoSessionScreen extends Component {

    dragX = new Value(0);
    dragY = new Value(0);
    offsetX = new Value(0);
    offsetY = new Value(0);
    gestureState = new Value(-1);
    onGestureEvent = event([{
        nativeEvent: {
            translationX: this.dragX,
            translationY: this.dragY,
            state: this.gestureState,
        }
    }]);
    transX = cond(
        eq(this.gestureState, State.ACTIVE),
        add(this.offsetX, this.dragX),
        set(this.offsetX, add(this.offsetX, this.dragX)),
    );
    transY = cond(
        eq(this.gestureState, State.ACTIVE),
        add(this.offsetY, this.dragY),
        set(this.offsetY, add(this.offsetY, this.dragY)),
    );

    renderLocalCameraThumbView = () => {
        return (
            <PanGestureHandler maxPointers={1} onGestureEvent={this.onGestureEvent} onHandlerStateChange={this.onGestureEvent}>
                <Animated.View style={{transform: [{translateX: this.transX}, {translateY: this.transY}], borderRadius: moderateScale(15), height: CARDHEIGHT, width: CARDWIDTH, overflow: 'hidden'}}>
                    <CameraLocalView enabled={true} style={{flex: 1}}/>
                </Animated.View>
            </PanGestureHandler>
        );
    }

}

推荐阅读