【问题标题】:React Native - PanGestureHandler does not work after changing the component stateReact Native - PanGestureHandler 在更改组件状态后不起作用
【发布时间】:2020-02-25 15:46:16
【问题描述】:

我有两个屏幕,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}
                />
            </>
        );
    }
}

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

谢谢。

【问题讨论】:

  • 当我将 translateX 和 translateY 的值存储在状态中时,它似乎可以工作,但是,它现在会在翻转后重置位置。

标签: react-native


【解决方案1】:

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

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

}

【讨论】:

  • 您解决的真正问题是什么?我有一个类似的问题。图像拖动仅在更新触发状态(true 或 false)后才能重新渲染。
  • 是否可以在 onGestureFunciton 中添加某种检查?还是我们只能直接使用事件?请看这个stackoverflow.com/questions/64330969/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-04
  • 1970-01-01
  • 2019-12-29
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多