Comments (30)
same issue !! onPressIn and onPressOut is work, but onPress not work only!
from react-native.
Just chiming in to say that we have been struggling with this as well. Both this issue and #36710 describe our problem quite well, although #36710 got hijacked and closed based on an unrelated bug being addressed (the solved bug had to do with the new architecture, while the OP stated his problem existed before the new architecture was even created).
Looking forward to any movement on this issue, because its random nature makes it effectively impossible to reliably reproduce.
from react-native.
@tcloudAce Thank you - however this issue is pretty much with anything pressable (not just a button). Buttons, navigation tabs, etc. I should also add that the app responds to presses for a very short period of time (<3 seconds) and then ceases responding to any taps anywhere on the Android device screen. The emulators work fine so this is very difficult to reproduce/test.
from react-native.
In my scenario, I can reproduce this error 100% of the time (onPress does not respond, but interestingly, the animation effect of TouchableOpacity still shows). I have tested it with Expo 51, Expo 50, React Native 0.74.1, and React Native 0.73.6. The test environment includes Samsung S23 and S24. In a real device environment, even onPressIn and onPressOut do not work, whereas on the emulator, onPressIn and onPressOut respond normally, but onPress does not respond.
My scenario is similar to a step-by-step installation guide Page, which is built with a ScrollView in RN. There are about 7 pages within the ScrollView. If a Modal is opened within these pages, the onPress of buttons inside the Modal does not respond. Currently, I have disabled react-native-screens and used onPressOut instead of onPress. Although it works, it causes accidental clicks when scrolling (due to onPressOut).
Additionally, to add more context, my ScrollView contains nested ScrollViews. In this environment, onPress 100% fails to respond. The issue does not occur with non-nested ScrollViews.
from react-native.
I have the same issue with our app. iOS and Android emulator work fine. iOS production app works fine. Recently though, the Android production app has become relatively unusable. You can log in and within a few seconds, pretty much every pressable item becomes unresponsive.
from react-native.
Will add, if needed
Can we get a reproducer? As otherwise it's extremely hard to debug this issue.
from react-native.
Yes, will follow later today.
from react-native.
Yes, will follow later today.
Any news on this?
from react-native.
Missing Reproducible Example | |
---|---|
âšī¸ | We could not detect a reproducible example in your issue report. Please provide either:
|
from react-native.
I edited the original post. This is the repro: https://github.com/DrZoidberg09/RN-Android-Touch-Issue/
from react-native.
@cortinico Anything else you need from me to look into this?
from react-native.
on Samsung devices onPress doesn't work. All customers with Samsung devices (S23, S24) are reporting it. any solution to make it work?
from react-native.
@imransilvake @DrZoidberg09 Using react-native-handler-gesture to build a button can temporarily solve this problem. Here is the sample code:
import React from "react";
import { TapGestureHandler, State } from "react-native-gesture-handler";
import { View } from "react-native";
export default function Pressable({ onPress, children, style, disabled }) {
const onHandlerStateChange = (event) => {
if (event.nativeEvent.state === State.END) {
onPress();
}
};
return (
{children}
);
}
from react-native.
@cortinico In my scenario, the TextInput also cannot be focused. This is indeed a peculiar issue.
from react-native.
@gtwilliams03 If the buttons are not working, you can try the following code:
`import React from "react";
import { TapGestureHandler, State } from "react-native-gesture-handler";
import { View } from "react-native";
export default function Pressable({ onPress, children, style, disabled }) {
const onHandlerStateChange = (event) => {
if (event.nativeEvent.state === State.END) {
onPress();
}
};
return (
{children}
);
}`
from react-native.
In my case, changing the component layout and applying the above code temporarily solved my problem. The only thing that is certain is that iOS and Android often cannot use the same layout. Code that runs successfully and without issues on Android usually works on iOS, but not the other way around. Moreover, this issue is not only present in the latest versions of React Native but has existed in many past versions as well. I hope this helps everyone.
from react-native.
Can we get a non-expo reproducer using this template instead:
https://github.com/react-native-community/reproducer-react-native
The provided repro is quite involved (uses expo router) and I'd like to isolate this issue as much as possible.
from react-native.
Tried to reproduce it with pure RN and the repo you shared. So far, I could not reproduce it. Even with the RN-Navigation header issue shown in the other Expo based repro.
So far, it seems it's neither react-native nor react-navigation, but Expo(-router).
But I will keep trying to reproduce it in the next days.
from react-native.
So far, it seems it's neither react-native nor react-navigation, but Expo(-router).
That's sometimes related to react-native-screens
(at least it was in the past). Worth a try with -screens
to see if it reproduces there
from react-native.
I have react-native-screens and react-navigation stack also running in the repro. Here it works fine. In the main project with Expo it is not.
Another weird behavior:
If I run Expo development build on the native device most is working pretty ok besides onPress in the header bar. (onPressOut and In is working nicely though). However, if I build a proper apk and run it on the native (Samsung) device. Everything pressable in a stack is not working, incl. every list, button, etc. (Also the positioning of position absolute items is different if I use development build or an apk on the same device...)
from react-native.
This seems to be very close to the issue as well: software-mansion/react-native-screens#2150
from react-native.
@cortinico I could track it down to expo-router. Please look at the github repo. I added a reproducer for each: pure RN, expo with router and expo without router.
The two repos without router work. With router it does not.
from react-native.
The two repos without router work. With router it does not.
Great so let's close it for now and move the conversation over to: expo/expo#30032
from react-native.
I was encountering a similar issue -- TouchableOpacity (and other wrappers of Pressable) not working on Android but working fine in iOS. However, I was able to fix the issue by adding a zIndex: 10
in the style property. 10 is just a number here, basically it had to be on the top.
from react-native.
I have done a little digging into Pressability.js
It seems that the condition to fire onPress is: isPressInSignal(prevState) && signal === 'RESPONDER_RELEASE'
and then that !isPressCanceledByLongPress
In my testings of this wonky behaviour.
- Sometimes, the events are in the right order (it's rare, but it is happening). (i get RESPONDER_ACTIVE_PRESS_IN as prevState)
- Sometime not at all, and when i get the RESPONDER_RELEASE signal, the prevState is RESPONDER_ACTIVE_PRESS_OUT and so onPress do not fire.
const isPressInSignal = (signal: TouchState) =>
signal === 'RESPONDER_INACTIVE_PRESS_IN' ||
signal === 'RESPONDER_ACTIVE_PRESS_IN' ||
signal === 'RESPONDER_ACTIVE_LONG_PRESS_IN';
onPressIn and onPressOut are not using the same State machine conditions, and thus, are not impacted by the issue.
Haven't fixed (as adding the prev event to the function is surely not what is supposed to happen), and i am trying to understand a bit more to not do shit, but maybe it can help someone understand more the issue.
from react-native.
I investigated it a little more and from what I see this is a case of measure not synchronizing correctly with the coordinates of touches.
On Android with new architecture the touches will be returned as coordinates relative to the root view. So if the screen you are using is 300 x 700 pixels, it will fall somewhere between that.
The Pressablity.js file, mentioned by @littleski then takes those touch coordinates and compares them to the coordinates of the responder (returned by the measure function),
_measureResponderRegion(): void {
if (this._responderID == null) {
return;
}
if (typeof this._responderID === 'number') {
UIManager.measure(this._responderID, this._measureCallback);
} else {
this._responderID.measure(this._measureCallback);
}
}
_measureCallback = (
left: number,
top: number,
width: number,
height: number,
pageX: number,
pageY: number,
) => {
if (!left && !top && !width && !height && !pageX && !pageY) {
return;
}
this._responderRegion = { // <------ position of the responder relative to the root view (this is the problematic place, which is explained below
bottom: pageY + height,
left: pageX,
right: pageX + width,
top: pageY,
};
};
BUT ONLY on the responder move:
onResponderMove: (event: PressEvent): void => {
/* ... */
const touch = getTouchFromPressEvent(event); // <--- coordinates of users touch
/* ... */
if (this._isTouchWithinResponderRegion(touch, responderRegion)) {
this._receiveSignal('ENTER_PRESS_RECT', event);
} else {
this._cancelLongPressDelayTimeout();
this._receiveSignal('LEAVE_PRESS_RECT', event);
}
},
_isTouchWithinResponderRegion(
touch: $PropertyType<PressEvent, 'nativeEvent'>,
responderRegion: $ReadOnly<{|
bottom: number,
left: number,
right: number,
top: number,
|}>,
): boolean {
/* ... */
return (
touch.pageX > regionLeft &&
touch.pageX < regionRight &&
touch.pageY > regionTop &&
touch.pageY < regionBottom
);
}
And that is why this issue only appears on some android devices which are more sensitive. Emulators and less sensitive devices will never trigger the onResponderMove callback. I found out that this issue can be reproduced on emulators just by moving the mouse a little bit during a touch.
As for the reason why this bug even occurs at all, it comes down to the data returned from the measure. The pageX and pageY in some special circumstances will return coordinates far exceeding the boundaries of the screen. From what I tested for now, this is a case for both react-native-tab-view
and react-native-pager-view
. I haven't found a time to look into them, what exact construct is causing that, but I know for sure that the responder pageX and pageY is being offset there by the amount of the travel distance it had to do before appearing on the screen.
Let's take tab-view for example:
If we have 3 tabs in tab-view , each screen-wide with it's own touchable button (responder), the responder coordinates for the first tab button will be normal - it will respond to touches correctly, but for the second and third tab the coordinates will be offset (pageX) by respectively (in case of 300 pixel wide screen) - 300 pixels and 600 pixels, meaning that as soon as the responder calls onResponderMove
the touch will be broken (put into LEAVE_PRESS_RECT state) which it then has no way of fixing, since the X position of the touch will be like 112 pixels and the responder X will be 412 pixels (out of screen).
For now I don't know how to fix it.
from react-native.
It's definitely a react-native-pager-view issue, since tab-view also relies on that, for now I simply swapped all the buttons in the app with this component
const ManuallyHandledButton = ({ onPress, children, ...props }) => {
const _touchActivatePositionRef = useRef(null)
const _onPressIn = useCallback((e) => {
const { pageX, pageY } = e.nativeEvent
_touchActivatePositionRef.current = {
pageX,
pageY
}
}, [])
const _onPress = useCallback(
(e) => {
const { pageX, pageY } = e.nativeEvent
const absX = Math.abs(_touchActivatePositionRef.current.pageX - pageX)
const absY = Math.abs(_touchActivatePositionRef.current.pageY - pageY)
const dragged = absX > PRECISION || absY > PRECISION
if (!dragged) {
onPress?.(e)
}
},
[onPress]
)
return (
<Pressable
onResponderStart={_onPressIn}
onResponderEnd={_onPress}
{...props}
>
{children}
</Pressable>
)
}
const PressableForwarder =
global?.nativeFabricUIManager && IS_ANDROID
? ManuallyHandledButton
: TouchableOpacity
export default PressableForwarder
And it seems to work good enough
from react-native.
Pigging backing on @DominikHinc
UiManager
const UIManager: UIManagerJSInterface = {
...UIManagerImpl,
measure(
reactTag: number,
callback: (
left: number,
top: number,
width: number,
height: number,
pageX: number,
pageY: number,
) => void,
): void {
if (isFabricReactTag(reactTag)) {
const FabricUIManager = nullthrows(getFabricUIManager());
const shadowNode =
FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag);
if (shadowNode) {
FabricUIManager.measure(shadowNode, callback);
} else {
console.warn(`measure cannot find view with tag #${reactTag}`);
// $FlowFixMe[incompatible-call]
callback();
}
} else {
// Paper
UIManagerImpl.measure(reactTag, callback);
}
},
So here is the difference between new arch and old which seems logic. need to dig a bit in the Java to understand the difference and what may have been broken in the new arch java binding.
from react-native.
@littleski turns out all I had to do was to implement this callstack/react-native-pager-view#836
from react-native.
The repro doesn't use this. It's more than likely that this is just a workaround for one lib. I don't use this package either. Might help understand the issue tho.
from react-native.
Related Issues (20)
- React Native 0.74.0 - Getting issue on production build -Crashed: Thread: SIGSEGV 0x0000006df6aebf90 HOT 6
- FlatList Items Not Occupying Full Screen Height with Paging Enabled HOT 3
- [Android] ScrollView does not properly handle `testID` property
- Application Scene Delegates support in RN >= 0.74 HOT 5
- How to initialize a react-native app of version 0.75.2 in year 2024? HOT 11
- Codegen resolves wrong dependency in multi-app monorepo; when apps specify different versions of same dep (ios) HOT 7
- Why support only Ukraine but not Palestine?Either support both or support neither. Why bring selective support into technology? HOT 4
- Tried to show an alert while not attached to an Activity HOT 5
- Unable to use Hermes engine in fresh CLI project HOT 10
- [email protected] / Android / New Arch - Bug HOT 5
- ForceRTL(false) is not working as intended HOT 6
- Bug: TextInput with multiline and lineHeight has height issue when controlled HOT 3
- [[email protected]] `yoga/style/Style.h` file not found HOT 10
- Creating a module with New Architecture and including a .swift file introduces compiler errors HOT 11
- [v0.75.2] macOS (Catalyst) builds fail with `hermes.framework: bundle format is ambiguous (could be app or framework)` HOT 27
- `Text` Components Positioned with bottom: 0 Gets Hidden Behind Navigation Bar on Android Devices HOT 29
- TypeError: Cannot read property 'create' of undefined, HOT 5
- Direct JSC debugging cannot be used in Mac simulator from 0.74.1 HOT 4
- Empty dSYM issue HOT 8
- * Where: Settings file 'C:\Users\Debasis\Desktop\vipani-app\android\settings.gradle' line: 13 * What went wrong: Error resolving plugin [id: 'com.facebook.react.settings'] HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
đ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. đđđ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google â¤ī¸ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-native.