使用旧版本的Expo,我创建了一个应用程序,该应用程序必须在按下自定义按钮时播放音频流,并且由于Expo不支持后台播放,因此我决定使用保持唤醒状态,并将该应用程序演化为通过将屏幕变黑来模拟睡眠。我知道这不是最佳解决方案,但是鉴于世博会的限制,这可能是我可以做出的最佳折衷方案。要开始倒计时,应该在屏幕上的任何位置检测到触摸,并且每次检测到触摸时,都必须重置倒计时。在浏览Expo版本时,有一次,我开始使用View的onTouchStartCapture,那时即使按下子TouchableOpacity按钮并且事件由孩子处理,它也可以工作并捕获触摸。
但是,现在使用37(我正在使用〜37.0.3)和React Native 37.0.1,一切都不同了,即使我在线上进行了研究,我还是有点迷失。
即使在孩子处理的情况下,是否也可以正确捕获父母中的触摸事件?我的意思是,即使事件是在父母中捕获的,孩子的行为也不应受到影响。我尝试在冒泡阶段进行捕获,但是无法按预期进行。
该代码过于复杂,无法发布有意义的示例,除了小片段外(可能用于SleepOverlay)。
const SLEEP_TIMEOUT_1 = 24000
, SLEEP_TIMEOUT_2 = 6000
class SleepOverlay extends React.Component {
_state = 0
_timeout1 = null
_timeout2 = null
state = {
opacity: .7
, visible: false
}
clearTimeouts = a => {
clearTimeout(this._timeout2)
clearTimeout(this._timeout1)
}
sleep = e => {
this.state = 3
this.setState({ opacity: 1, visible: false })
this.setState({ visible: true })
}
shade = e => {
this.state = 2
this.setState({ visible: true })
this._timeout2 = setTimeout(this.sleep, SLEEP_TIMEOUT_2)
}
wait = a => {
this.clearTimeouts()
this.state = 1
this._timeout1 = setTimeout(this.shade, SLEEP_TIMEOUT_1)
}
constructor(props) {
super(props)
const onInit = this.props.onInit
if(onInit)
onInit(this.wait)
}
componentWillUnmount() {
this.clearTimeouts()
this.state = 0
}
componentDidUpdate() {
if(this.props.visible) {
if(this.state === 0)
this.wait()
} else {
this.clearTimeouts()
this.state = 0
}
}
pressed = e => {
this.state = 0
this.setState({ opacity: .7, visible: false })
}
style() {
return {
position: 'absolute'
, top: 0
, right: 0
, bottom: 0
, left: 0
, backgroundColor: '#000'
, opacity: this.state.opacity
}
}
render() {
return (
this.state.visible && this.props.visible && (
<TouchableOpacity
style={ this.style() }
onPress={ this.pressed }
/>
) || <></>
)
}
}
应用程序:
sleepReset() {}
captureTouched = a => this.sleepReset()
initSleepOverlay = f => this.sleepReset = f
渲染:
return (
<View
onTouchStartCapture={ this.captureTouched }
>
<ScrollView
>
</ScrollView>
{isIOS && isPortrait &&
<TouchableOpacity style={ styles.iosBar } />
}
<SleepOverlay visible={ state.tag } onInit={ this.initSleepOverlay } />
</View>
)