React Native - 更改组件状态后 PanGestureHandler 不起作用 [英] React Native - PanGestureHandler does not work after changing the component state

查看:91
本文介绍了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';从'react-native-size-matters'中导入{中等规模};import { PanGestureHandler, State } from 'react-native-gesture-handler';import { onGestureEvent } from 'react-native-redash';从'react-native-flip-view-next'导入FlipView;从react-native-reanimated"导入动画从 './../screens/ChatScreen' 导入 ChatScreen;const { Value, diffClamp, cond, set, eq, add } = 动画;const DEVICE_WIDTH = Dimensions.get('window').width;const DEVICE_HEIGHT = Dimensions.get('window').height;const CARDWIDTH = mediumScale(120);const CARDHEIGHT = mediumScale(160);const withOffset = (value: Animated.Value, state: Animated.Value) =>{常量偏移量 = 新值(0)return cond(eq(state, State.END), [set (offset, add(offset, value)), offset], add(offset, value));};导出默认类 VideoSessionScreen 扩展组件 {状态 = {isFlipped:假,...}renderCameraThumbView = () =>{const state = new Value(-1);const translationX = 新值(0);const translationY = 新值(0);constgestureHandler = 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));返回 (<PanGestureHandler {...gestureHandler}><Animated.View style={{transform: [{translateX}, {translateY}], borderRadius: mediumScale(15), height: CARDHEIGHT, width: CARDWIDTH, overflow: 'hidden'}}>{!this.state.isFlipped &&<CameraLocalView enabled={true} style={{flex: 1}}/>}{this.state.isFlipped &&<视图样式={{flex: 1, backgroundColor: '#111111'}}>{Array.from(this.state.videoTracks, ([sid, trackId]) => {返回 (<CameraRemoteView/>)})}</查看>}</Animated.View></PanGestureHandler>);};_renderFront() {返回(<SafeAreaView style={{flex: 1, backgroundColor: '#111'}}>{'local' === this.state.cameraView &&<><View style={{position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, backgroundColor: 'red'}}></查看><Animated.View style={{position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, padding: mediumScale(15)}}>{this.renderCameraThumbView()}</Animated.View></>}</SafeAreaView>);}_renderBack() {返回(<视图样式={{flex: 1}}><聊天画面didPressBackBtn = {() =>{this.setState({isFlipped: 假})}}/></查看>)}使成为() {返回 (<><FlipView style={{flex: 1}}前={this._renderFront()}back={this._renderBack()}isFlipped={this.state.isFlipped}翻转轴=y"flipEasing={Easing.out(Easing.ease)}翻转持续时间={500}透视={1000}/></>);}}

在我调用 this.state({{isFlipped: !this.state.isFlipped}}) 后 PanGestureHandler 无法工作的可能原因是什么,我该如何解决?>

谢谢.

解决方案

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

import React, { Component } from 'react';从'react-native-size-matters'中导入{中等规模};import { PanGestureHandler, State } from 'react-native-gesture-handler';从react-native-reanimated"导入动画const { cond, eq, add, set, Value, event } = Animated;const CARDWIDTH = mediumScale(120);const CARDHEIGHT = mediumScale(160);导出默认类 VideoSessionScreen 扩展组件 {dragX = 新值(0);dragY = 新值(0);offsetX = 新值(0);offsetY = 新值(0);手势状态 = 新值(-1);onGestureEvent = 事件([{本机事件:{翻译X:this.dragX,翻译Y: this.dragY,状态:this.gestureState,}}]);transX = 条件(eq(this.gestureState, State.ACTIVE),添加(this.offsetX,this.dragX),设置(this.offsetX,添加(this.offsetX,this.dragX)),);transY = cond(eq(this.gestureState, State.ACTIVE),添加(this.offsetY,this.dragY),设置(this.offsetY,添加(this.offsetY,this.dragY)),);renderLocalCameraThumbView = () =>{返回 (<PanGestureHandler maxPointers={1} onGestureEvent={this.onGestureEvent} onHandlerStateChange={this.onGestureEvent}><Animated.View style={{transform: [{translateX: this.transX}, {translateY: this.transY}], borderRadius: mediumScale(15), height: CARDHEIGHT, width: CARDWIDTH, overflow: 'hidden'}}><CameraLocalView enabled={true} style={{flex: 1}}/></Animated.View></PanGestureHandler>);}}

I have two screens, 1) Video calling screen 2) Chat screen.

I have implemented flip view using the library https://github.com/kevinstumpf/react-native-flip-view to show video calling screen as front screen, and when someone clicks on chat, flip the view and show chat as back screen.

I want to show a thumbnail camera view in chat and video calling screen with draggable view, it works on first load, however when I flip the screen, the PanGestureHandler stops working, although I can see the camera thumbnail view is still visible in the screen after the flip, however its position gets reset to top left corner (initial position) and drag is no more working.

Below is the code I am using.

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}
                />
            </>
        );
    }
}

What could be the possible cause that PanGestureHandler does not work after I call this.state({{isFlipped: !this.state.isFlipped}}), how can I fix this?

Thanks.

解决方案

I had to redo and implement it the following way, which works perfectly now.

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>
        );
    }

}

这篇关于React Native - 更改组件状态后 PanGestureHandler 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆