反应本机检测长按结束

时间:2017-06-08 19:53:41

标签: react-native touch

我的问题非常简单,我正在尝试检测onLongPress事件的结束。基本上当用户释放印刷机时。

我在TouchableWithoutFeedback尝试了所有可能的事件,但一次只触发一个事件。

import React from 'react'

import {
	View,
	Text,
	Dimensions,
	CameraRoll
} from 'react-native'

import Camera from 'react-native-camera';

const { width, height } = Dimensions.get('window')
class ImageBrowser extends React.Component {
	static navigationOptions = {
		title: 'Unsplash Images',
	}

	state = {
		images: [],
		loading: true,
		page: 1,
		isRecording : false
	}

	takeVideo(){
		this._recordVideo.bind(this);
	}

	_recordVideo(){
		this.camera.capture({mode: Camera.constants.CaptureMode.video})
			.then((data) => {
				console.log(data);
			})
			.catch((err) => {
				console.log(err)
			})
	}

	_stopRecord(){
		this.camera.stopCapture();
	}

	render() {
		return (
			<View style={{flex: 1}}>
				<Camera
					ref={(cam) => {this.camera = cam;}}
					style={styles.preview}
					aspect={Camera.constants.Aspect.fill}
					type={Camera.constants.Type.front}
				>
					<Text style={styles.capture} onLongPress={this.takeVideo.bind(this)} onPress={this._stopRecord.bind(this)} onPressOut={this._stopRecord.bind(this)}>[CAPTURE]</Text>
				</Camera>
			</View>
		)
	}
}

const styles = {
	preview: {
		flex: 1,
		justifyContent: 'flex-end',
		alignItems: 'center',
		height: Dimensions.get('window').height,
		width: Dimensions.get('window').width
	},
	capture: {
		flex: 0,
		backgroundColor: '#fff',
		borderRadius: 5,
		color: '#000',
		padding: 10,
		margin: 40
	}
}

export default ImageBrowser

6 个答案:

答案 0 :(得分:2)

回答我自己的问题。我最后使用了Gesture Responder

onStartShouldSetResponder =&gt;检测用户何时开始按下元素onResponderRelease =&gt;检测用户何时停止按元素

以下是官方文档中使用PanResponder制作视图提取手势的示例:

class ExampleComponent extends Component {
    constructor(props) {
      super(props)
      this._panResponder = PanResponder.create({
        // Ask to be the responder:
        onStartShouldSetPanResponder: (evt, gestureState) => true,
        onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
        onMoveShouldSetPanResponder: (evt, gestureState) => true,
        onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

        onPanResponderGrant: (evt, gestureState) => {
          // The gesture has started. Show visual feedback so the user knows
          // what is happening!

          // gestureState.d{x,y} will be set to zero now
        },
        onPanResponderMove: (evt, gestureState) => {
          // The most recent move distance is gestureState.move{X,Y}

          // The accumulated gesture distance since becoming responder is
          // gestureState.d{x,y}
        },
        onPanResponderTerminationRequest: (evt, gestureState) => true,
        onPanResponderRelease: (evt, gestureState) => {
          // The user has released all touches while this view is the
          // responder. This typically means a gesture has succeeded
        },
        onPanResponderTerminate: (evt, gestureState) => {
          // Another component has become the responder, so this gesture
          // should be cancelled
        },
        onShouldBlockNativeResponder: (evt, gestureState) => {
          // Returns whether this component should block native components from becoming the JS
          // responder. Returns true by default. Is currently only supported on android.
          return true;
        },
      });
    }

    render() {
      return (
        <View {...this._panResponder.panHandlers} />
      );
    }
  }

答案 1 :(得分:2)

答案 2 :(得分:1)

更好的解决方案是应用@yongqian_iOS的建议并执行以下操作:

<TouchableOpacity
   onPressOut={ () => console.warn('ENDED') }
   onLongPress={ () => console.warn('STARTED LONG PRESS') } 
/>

答案 3 :(得分:0)

我不太确定我是否理解您的问题,但是当我尝试解决类似问题时,该问题出现在我的Google搜索中。对于未来的读者来说,这是我创建一个可以进行动画效果的按钮的方法,但是仅在未取消操作时(通过拖动手指或滚动父级ScrollView for ex)触发操作。

import PropTypes from 'prop-types';
import React from 'react';
import { TouchableWithoutFeedback, Animated } from 'react-native';
// Vector Icons from here ♥‿♥: https://github.com/oblador/react-native-vector-icons
import { Feather } from '@expo/vector-icons';

export default class tomatoButt extends React.Component {
  static propTypes = {
    onPress: PropTypes.func.isRequired,
  };

  // No constructors needed! ┌(ㆆ㉨ㆆ)ʃ
  state = {
    animatedTouchScale: new Animated.Value(1),
  }

  animationStep = (toValue, callback, duration) => {
    const { animatedTouchScale } = this.state;
    Animated.timing(animatedTouchScale, {
      toValue,
      duration: duration || 100,
      useNativeDriver: true,
    }).start(callback);
  }

  // Scale the button down when the user "hovers" on it
  handlePressIn = () => this.animationStep(0.95);

  // Always scale out again, regardless if the touch is cancelled
  handlePressOut = () => this.animationStep(1);

  // If the user taps without holding, then animate in, trigger onPress, and animate out
  handlePress = () => {
    // onPress is an external function. Ex:
    // () => Alert.alert("Don't stop... (づ。◕‿‿◕。)づ")
    const { onPress } = this.props;
    this.animationStep(0.95, () => {
      onPress();
      this.animationStep(1, () => {}, 50);
    }, 50);
  }

  render() {
    return (
      <TouchableWithoutFeedback
         // Called first, when you first touch
        onPressIn={this.handlePressIn}
         // Called second, regardless if the touch is cancelled
        onPressOut={this.handlePressOut}
         // Called last, only when touch is released, but not if it's cancelled
        onPress={this.handlePress}
      >
        <Animated.View
          style={{
            // We'll scale the button down on touches:
            transform: [{ scale: animatedTouchScale }],
            // You should move these styles to an external sheet:
            backgroundColor: 'tomato',
            width: '100%',
            justifyContent: 'center',
            alignItems: 'center',
            borderRadius: 5,
            padding: 20,
            marginTop: 1,
            marginBottom: 1,
          }}
        >
          {/* Plus icon, OS independent */}
          <Feather
            name="plus"
            size={18}
            color="white"
          />
        </Animated.View>
      </TouchableWithoutFeedback>
    );
  }
}

答案 4 :(得分:0)

this.panResponder = PanResponder.create({
    onPanResponderRelease: (e, gestureState) => {
        Animated.timing(this.state.visible, {
            toValue: 0,
            duration: 200,
            useNativeDriver: true,
        }).start();
    },
}

答案 5 :(得分:0)

使用 onPressInonPressOut 方法捕获触摸事件的开始和结束。 onPressIn 回调在用户触摸组件时调用,onPressOut 将在用户松开触摸时触发。

<TouchableOpacity
   onPressIn={ () => console.warn('Touch started') }
   onPressOut={ () => console.warn('Touch ended') } 
/>