Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to make android webview based app less sensitive in interpreting taps as small drags?

I have and C# Xamarin android app that hosts a reactjs app in a webview.

When using this app on a touch screen android device, It appears that occasionally tapping the screen is ignored.

What appears to be going on is that, the tap is interpreted as a mini drag event, as there was some small directional movement in the tap.

Looking at the android logs, for failed taps, I noticed output like the following:

adb -d logcat -s CustomFrequencyManagerService

06-19 13:35:49.225  2945  9989 D CustomFrequencyManagerService: acquireDVFSLockLocked : type : DVFS_MIN_LIMIT  frequency : 839000  uid : 1000  pid : 2945  pkgName : GESTURE_DETECTED@CPU_MIN@49
06-19 13:35:49.781  2945  2945 D CustomFrequencyManagerService: releaseDVFSLockLocked : Getting Lock type frm List : DVFS_MIN_LIMIT  frequency : 839000  uid : 1000  pid : 2945  tag : GESTURE_DETECTED@CPU_MIN@49

Note the GESTURE_DETECTED part of the log entry.

However for successful taps, CustomFrequencyManagerService has no output in the log.

Looking at this from the reactjs app perspective:

I noticed that the failed taps emit the following events:

touchstart
touchend

While the normal successful events are:

touchstart
touchend
mousedown
blur
mouseup
click

I could potentially change the reactjs app to respond directly to touch events instead of click events, but I was wondering if there was a way (hopefully programmatically via android app) to alter the sensitivity with regard to what's interpreted as a drag as opposed to a click?

By installing a IOnTouchListener on the Android.WebKit.WebView

_webView.SetOnTouchListener(new GestureIgnoreTouchListener());

I was able to see at what movement threshold a click turned into a drag.

    public class GestureIgnoreTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
    {
        float _x;
        float _y;

        public bool OnTouch(Android.Views.View v, MotionEvent e)
        {
            if (e.Action == MotionEventActions.Down)
            {
                _x = e.RawX;
                _y = e.RawY;
                
                return false;
            }
            if (e.Action == MotionEventActions.Up)
            {
                var diffX = e.RawX - _x;
                var diffY = e.RawY - _y;

                var distance = Math.Sqrt(Math.Pow(diffX, 2) + Math.Pow(diffY, 2));
                // observed: 
                // if distance is 10 or less then this is interpreted as a click.
                // if distance is 12 or greater, click is not emitted.
                Console.WriteLine(distance);

                return false;
            }

            return false;
        }
    }

Ideally, if the distance was between 10 and 50, I would like to be able to make this be considered a click not a drag. Possibly I could create a synthetic click event, in this case, but I'm hoping I can somehow influence what ever android code is responsible for interpreting this as a drag.

like image 749
Tom Avatar asked Jun 26 '20 16:06

Tom


People also ask

Is Android WebView deprecated?

Beginning October 5, 2021, Facebook Login will no longer support using Android embedded browsers (WebViews) for logging in users.

What version of Chrome does Android WebView use?

# What version of Chrome is it based on? The WebView shipped with Android 4.4 (KitKat) is based on the same code as Chrome for Android version 30. This WebView does not have full feature parity with Chrome for Android and is given the version number 30.0. 0.0.

What is setWebViewClient?

To open links clicked by the user, simply provide a WebViewClient for your WebView, using setWebViewClient(). Demo of creating an application to open any URL inside the application and clicking on any link from that URl. should not open Native browser but that URL should open in the same screen.

Which method can be used to retrieve web setting in Android?

Configuring WebView Settings with WebSettings getSettings() object if a WebView is already destroyed. You can retrieve WebSettings with WebView. getSettings() API.


1 Answers

There are two approaches I've seen people use for this situation. The first you already mentioned: tell react when you're in touch screen environment to use tap events instead of click events.

The second is to take into account what Android refers to as "touch slop":

From https://developer.android.com/training/gestures/movement.html:

Because finger-based touch isn't always the most precise form of interaction, detecting touch events is often based more on movement than on simple contact. To help apps distinguish between movement-based gestures (such as a swipe) and non-movement gestures (such as a single tap), Android includes the notion of "touch slop". Touch slop refers to the distance in pixels a user's touch can wander before the gesture is interpreted as a movement-based gesture. For more discussion of this topic, see Managing Touch Events in a ViewGroup.

Google provides an example of one way to deal with it in a difference context here: https://developer.android.com/training/gestures/viewgroup#vc which you could probably adapt to your situation.

like image 110
lfalin Avatar answered Oct 04 '22 01:10

lfalin