【问题标题】:React native detect end of long press反应原生检测长按结束
【发布时间】:2017-06-08 19:53:40
【问题描述】:

我的问题很简单,我正在尝试检测 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

【问题讨论】:

  • 分享您的代码以检查功能
  • @arunkumar 已编辑

标签: react-native touch


【解决方案1】:

【讨论】:

  • 这就是我要找的!谢谢
【解决方案2】:

更好的解决方案是应用@yongqian_iOS 的建议并做:

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

【讨论】:

  • onPressIn 可用于保持。
  • 非常感谢,您的回答对我帮助很大!
【解决方案3】:

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

onStartShouldSetResponder => 检测用户何时开始按下元素 onResponderRelease => 检测用户何时停止按下该元素

以下是官方文档中使用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} />
      );
    }
  }

【讨论】:

  • 你能分享一段你的代码吗?看看你是如何解决这个问题的。
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-24
        • 2018-07-04
        • 1970-01-01
        • 2018-12-17
        • 2021-12-14
        • 1970-01-01
        • 1970-01-01
        • 2021-10-20
        相关资源
        最近更新 更多