如何在PanGestureHandler中设置react-native-gesture-handler的初始偏移量?

时间:2019-08-21 23:23:56

标签: react-native

在下面的简单滑块(打字稿)示例中,react-native-gesture-handler中的PanGestureHandler仅在手势开始后设置。用户需要移动手指。

这是我想要实现的目标:点击也应设置滑块值(包括点击和拖动)。这是一种常见的模式,例如在搜索视频文件或将音量设置为最大然后进行调整时。

我想我可以将其包装在TapGestureHandler中,但是我正在寻找最优雅的方式来实现这一目标,而又不需要太多样板。

// example extracted from https://www.npmjs.com/package/react-native-reanimated-slider
import React, { Component } from 'react';
import Animated from 'react-native-reanimated';
import { PanGestureHandler, State } from 'react-native-gesture-handler';

const { Value, event, cond, eq, Extrapolate, interpolate } = Animated;

interface IProps {
    minimumTrackTintColor: string;
    maximumTrackTintColor: string;
    cacheTrackTintColor: string;
    value: number;
    style: any;
    cache;
    onSlidingStart;
    onSlidingComplete;
}
class Slider extends Component<IProps, {}> {
    static defaultProps = {
        minimumTrackTintColor: '#f3f',
        maximumTrackTintColor: 'transparent',
        cacheTrackTintColor: '#777',
    };

    private gestureState;
    private x;
    private width;
    private clamped_x;
    private onGestureEvent;

    public constructor(props: IProps) {
        super(props);

        this.gestureState = new Value(State.UNDETERMINED);
        this.x = new Value(0);
        this.width = new Value(0);

        this.clamped_x = cond(
            eq(this.width, 0),
            0,
            interpolate(this.x, {
                inputRange: [0, this.width],
                outputRange: [0, this.width],
                extrapolate: Extrapolate.CLAMP,
            })
        );

        this.onGestureEvent = event([
            {
                nativeEvent: {
                    state: this.gestureState,
                    x: this.x,
                },
            },
        ]);
    }

    onLayout = ({ nativeEvent }) => {
        this.width.setValue(nativeEvent.layout.width);
    };

    render() {
        const { style, minimumTrackTintColor, maximumTrackTintColor } = this.props;

        return (
            <PanGestureHandler
                onGestureEvent={this.onGestureEvent}
                onHandlerStateChange={this.onGestureEvent}
            >
                <Animated.View
                    style={[
                        {
                            flex: 1,
                            height: 30,
                            overflow: 'visible',
                            alignItems: 'center',
                            justifyContent: 'center',
                            backgroundColor: '#3330',
                        },
                        style,
                    ]}
                    onLayout={this.onLayout}
                >
                    <Animated.View
                        style={{
                            width: '100%',
                            height: 5,
                            borderRadius: 2,
                            overflow: 'hidden',
                            borderWidth: 1,
                            backgroundColor: maximumTrackTintColor,
                        }}
                    >
                        <Animated.View
                            style={{
                                backgroundColor: minimumTrackTintColor,
                                height: '100%',
                                maxWidth: '100%',
                                width: this.clamped_x,
                                position: 'absolute',
                            }}
                        />
                    </Animated.View>
                </Animated.View>
            </PanGestureHandler>
        );
    }
}

export default Slider;

谢谢!

编辑:这可以按预期工作,但是有一个可见的渲染怪癖,并且延迟很小。

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

const { Value, event, cond, eq, Extrapolate, interpolate } = Animated;

interface IProps {
    minimumTrackTintColor?: string;
    maximumTrackTintColor?: string;
    cacheTrackTintColor?: string;
    value: number;
    style?: any;
    onSlidingStart;
    onSlidingComplete;
}
class Slider extends Component<IProps, {}> {
    static defaultProps = {
        minimumTrackTintColor: '#f3f',
        maximumTrackTintColor: 'transparent',
        cacheTrackTintColor: '#777',
    };

    private gestureState;
    private x;
    private width;
    private clamped_x;
    private onGestureEvent;
    private onTapGesture;
    public constructor(props: IProps) {
        super(props);

        this.gestureState = new Value(State.UNDETERMINED);
        this.x = new Value(0);
        this.width = new Value(0);

        this.clamped_x = cond(
            eq(this.width, 0),
            0,
            interpolate(this.x, {
                inputRange: [0, this.width],
                outputRange: [0, this.width],
                extrapolate: Extrapolate.CLAMP,
            })
        );

        this.onGestureEvent = event([
            {
                nativeEvent: {
                    state: this.gestureState,
                    x: this.x,
                },
            },
        ]);

        this.onTapGesture = event([
            {
                nativeEvent: {
                    state: this.gestureState,
                    x: this.x,
                },
            },
        ]);
    }

    onLayout = ({ nativeEvent }) => {
        this.width.setValue(nativeEvent.layout.width);
    };

    render() {
        const { style, minimumTrackTintColor, maximumTrackTintColor } = this.props;

        return (
            <TapGestureHandler
                onGestureEvent={this.onTapGesture}
                onHandlerStateChange={this.onTapGesture}
            >
                <Animated.View>
                    <PanGestureHandler
                        onGestureEvent={this.onGestureEvent}
                        onHandlerStateChange={this.onGestureEvent}
                    >
                        <Animated.View
                            style={[
                                {
                                    flex: 1,
                                    height: 30,
                                    overflow: 'visible',
                                    alignItems: 'center',
                                    justifyContent: 'center',
                                    backgroundColor: '#3330',
                                },
                                style,
                            ]}
                            onLayout={this.onLayout}
                        >
                            <Animated.View
                                style={{
                                    width: '100%',
                                    height: 5,
                                    borderRadius: 2,
                                    overflow: 'hidden',
                                    borderWidth: 1,
                                    backgroundColor: maximumTrackTintColor,
                                }}
                            >
                                <Animated.View
                                    style={{
                                        backgroundColor: minimumTrackTintColor,
                                        height: '100%',
                                        maxWidth: '100%',
                                        width: this.clamped_x,
                                        position: 'absolute',
                                    }}
                                />
                            </Animated.View>
                        </Animated.View>
                    </PanGestureHandler>
                </Animated.View>
            </TapGestureHandler>
        );
    }
}

export default Slider;

1 个答案:

答案 0 :(得分:1)

几次阅读文档后,我发现了。它比预期的要简单:)

<PanGestureHandler
   onGestureEvent={this.onGestureEvent}
   onHandlerStateChange={this.onGestureEvent}
   minDist={0}
>

属性minDist可以设置为0

相关问题