Как сделать TouchableOpacity или TouchableHighlight кликабельными на устройствах, поддерживающих 3d touch (force touch)

88
8

У меня есть этот код:


<View {...this.panGesture.panHandlers}>
<Animated.View>

<View style={{ position: 'absolute' }}>
<TouchableHighlight onPress={ () => {console.log('hello')}>
</TouchableHighlight>
</View>

</Animated.View>
</View>


и я не могу ради своей любви использовать onPress для работы с iPhone'ами ​​6 и более, когда включен 3D-сенсор.


Я пробовал большинство предлагаемых решений здесь, но не повезло.


Буду признателен за любую помощь!

спросил(а) 2021-01-25T17:04:07+03:00 4 месяца, 2 недели назад
1
Решение
78

Мне удалось решить эту конкретную проблему, убедившись, что родительский PanResponder не захватывает ответчика при перемещении, пока касание не переместится с начала координат:


PanResponder.create({

//... other responder callbacks

onMoveShouldSetPanResponder(e, gestureState) {
if (gestureState.dx === 0 || gestureState.dy === 0) {
return false;
}
return true;
}
});

Это снова было вокруг React Native 0.10 дней, с тех пор не пробовал. Надеюсь, это поможет!

ответил(а) 2021-01-25T17:04:07+03:00 4 месяца, 2 недели назад
45

Хорошо после многого с этим, я понял, что решение было частично тем, что сказал jevakallio, НО я больше не могу использовать Touchables, когда 3D-сенсор включен, поэтому я должен воспроизвести их поведение вручную.


Теперь мой код выглядит так:
дочерний код:


let touchable;

if (View.forceTouchAvailable === false) { // if 3d touch is disabled
// just use a Touchable and all should be fine.
touchable = (<TouchableHighlight
onPress={ () => {console.log('hello world');}
style={this.props.style}
underlayColor={this.props.highlightBgColor}
>
{this.props.children}
</TouchableHighlight>);
} else { // Otherwise if 3D touch is enabled
// we'll have to use a child view WITH a PanResponder
touchable = (<View
style={[this.props.style, {
backgroundColor: this.state.panViewIsTapped ?
this.props.highlightBgColor
:
bgColor,
}]}
{...this.panResponderChild.panHandlers}
>
{this.props.children}
</View>);
}

return (<View {...this.panResponderParent.panHandlers}>
<Animated.View>

<View style={{ position: 'absolute' }}>
{touchable}
</View>

</Animated.View>
</View>);


дочерний код ответчика (this.panResponderChild):

this.panResponderChild = PanResponder.create({

// true because we want tapping on this to set it as the responder
onStartShouldSetPanResponder: () => true,

// true because we want this to capture the responder lock from it parent on start
onStartShouldSetPanResponderCapture: () => true,

// when the pan responder lock is terminated, set the pan view as NOT tapped
onPanResponderTerminate: () => {
this.setState({ panViewIsTapped: false });
},

// true so that the parent can grab our responder lock if he wan'ts to.
onPanResponderTerminationRequest: () => true,

// false because we DON'T want this btn capturing the resp lock from it parent on move
onMoveShouldSetPanResponderCapture: () => false,

// false because we DON'T want moving the finger on this to set it as the responder
onMoveShouldSetPanResponder: () => false,

onPanResponderGrant: () => {
this.setState({ panViewIsTapped: true });
},

onPanResponderRelease: () => {
this.setState({ panViewIsTapped: false });
console.log('hello world');
},
})


родительский фильтр отклика (this.panResponderParent):


this.panResponderParent = PanResponder.create({

// true because we want tapping on the cal, to set it as a responder
onStartShouldSetPanResponder: () => true,

// false because we DON'T want to grab the responder lock from our children on start
onStartShouldSetPanResponderCapture: () => false,

/*
onMoveShouldSetPanResponderCapture:
false because we don't want to accidentally grab the responder lock from
our children on movement.
That because sometimes even a small tap contains movement,
and thus a big percentage of taps will not work.
Keeping that flag false does not nessecarily mean that our children will
always capture the responder lock on movement, (they can if they want),
we're just not strict enough to grab it from them.
*/
onMoveShouldSetPanResponderCapture: () => false,

/*
onMoveShouldSetPanResponder:
We DO want moving the finter on the cal, to set it as a responder,
BUT, we don't always want moving the finger on an appointment setting this parent
as the responder.

Logic:
So, when the dx AND dy of the pan are 0, we return false, because we don't
want to grab the responder from our appointment children.

For anything other than that we just allow this parent to become the responder.

(dx, dy: accumulated distance of the gesture since the touch started)
*/
onMoveShouldSetPanResponder: (e, gestureState) =>
!(gestureState.dx === 0 || gestureState.dy === 0),

});

ответил(а) 2021-01-25T17:04:07+03:00 4 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема