Support input cancellation
On Android, you should avoid using the ACTION_DOWN event of OnTouchListener, because users will not be able to cancel their interaction. Actions should only be activated through an ACTION_UP event. Use an OnClickListener instead, because it has built-in support for cancellation.
kotlin
webView.setOnTouchListener { _, event ->
if (event == MotionEvent.ACTION_DOWN) {
// Use OnClickListener instead
}
} In Jetpack Compose, you should avoid execution actions before user finishes the click gesture (such as click or long press). Standard Composables or Composables with the clickable.clickable(kotlin.Boolean,kotlin.String,androidx.compose.ui.semantics.Role,kotlin.Function0)) modifier have built-in support for cancellation.
If you need more fine-grained control over gestures, you need to wait for the action to be released. This can be done, by using for example, tryAwaitRelease) for click actions.
kotlin
Box(
modifier = Modifier
.pointerInput(Unit) {
detectTapGestures(
onPress = {
if (tryAwaitRelease()) {
// your action ...
}
}
)
}
) On iOS, you should avoid using touchesBegan or UIControlEventTouchDown because users will not be able to cancel their interaction. Actions should only be activated through up events. Use a UITapGestureRecognizer instead, because it has built-in support for cancellation.
swift
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Use UITapGestureRecognizer instead
} In SwiftUI, you should avoid performing actions in response to gestures in onChanged) or updating) methods because users will not be able to cancel their interaction. Actions should only be activated through onEnded) method.
When implementing gestures, use SwiftUI's built-in gestures that have support for cancellation upon touchUp events.
swift
Text("Appt")
.gesture(LongPressGesture()
.onChanged { _ in
// Avoid activating actions before user has finished or cancelled touch
}
.onEnded { _ in
// Activate action when the touch event is finished
}) On Flutter, be careful when using a GestureDetector Avoid using events such as onDown, like onTapDown and onLongPressDown, because users will not be able to cancel their interaction. Use onAction events such onTap or onLongPress instead, because these have built-in support for cancellation.
dart
@override
Widget build(BuildContext context) {
return new GestureDetector(
onDown: ... // Use onTap instead
);
} In React Native, be careful when using PressEvent. Avoid using events like onPressIn, because users will not be able to cancel their interaction. Use events like onPress instead, because these have built-in support for cancellation.
jsx
<Pressable
onPressIn={() => {
// Use onPress instead
}}
/> In MAUI, you can simply use the IsEnabled property if you want to disable user interaction. You can also subscribe to the Command, Clicked, or Pressed/Released events if the component is actionable, like a Button. If the component doesn't offer an action, you can use any Gesture Recognizer to capture user interactions.
csharp
var button = new Button();
button.Clicked += (sender, args) =>
{
//Apply any logic
};
button.Pressed += (sender, args) =>
{
//Apply any logic
};
button.Released += (sender, args) =>
{
//Apply any logic
}; csharp
<Button Text="Hello"
Clicked="Button_Clicked"
Pressed="Button_Pressed"
Released="Button_Released" /> In Xamarin.Forms, be careful when building a CustomRenderer to detect touch events. Make sure not to use the down event for actions. For tap events, you should use TapGestureRecognizer.
csharp
// Android CustomRenderer
public override bool OnTouchEvent(MotionEvent event)
{
if (e.Action == MotionEventActions.Down)
{
// Don't use down event
}
return base.OnTouchEvent(event);
}
// iOS CustomRenderer
public override void TouchesBegan(NSSet touches, UIEvent event)
{
// Don't use down event
base.TouchesBegan(touches, event);
}