0

Background: I have a custom WebViewClient displaying an interactive webpage in kiosk mode, no external links etc. Therefore, it doesn't make any sense to have long touch actions, since they do nothing. So what I'd like to do is when a long touch is performed, usually from a user holding down slightly too long (500 ms isn't much) on a button for navigation, I'd like to perform the short touch action. This is complicated by the fact that the webpage is contained entirely in the javascript, no android views are used beyond the main webview window. So I need a way to execute a short touch with the same parameters (location etc) as the long touch.

Things I have tried: Attempt 1: Android Press LongClickListener get X, Y Coordinates, OnTouchListener

Resulting in:

PressEvent press;

class PressEvent {
    MotionEvent ev;

    public PressEvent(MotionEvent event) {
        ev = event;
    }
}

launchMethod (abbreviated for brevity) {
    view = (WebView) findViewById(R.id.mainWebview);
    view.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            final int action = event.getAction();
            switch (action & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                   press = new PressEvent(event);
                   break;
            }
            return false;
        }
    });

    view.setOnLongClickListener(new OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            log.debug("HERE");
            MotionEvent newEvent = MotionEvent.obtain(press.ev.getDownTime(), press.ev.getDownTime() + 499, MotionEvent.ACTION_DOWN, press.ev.getX(), press.ev.getY(), press.ev.getMetaState());
            view.dispatchTouchEvent(newEvent);
            newEvent.recycle();
            return true;
        }
    });

This appears to not work at all, though I do see my "HERE" debug statement. Attempt 2, some combination of: How to simulate a touch event in Android?

How do I "restart" a touch event in Android?

programmatically execute Touch event in android

Resulting in:

    int longPress = ViewConfiguration.getLongPressTimeout();

    view.setOnTouchListener(new OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            long timeHeld = event.getEventTime() - event.getDownTime();
            log.debug(timeHeld);
            log.debug(event.getAction());
            if (timeHeld > longPress && event.getAction() == MotionEvent.ACTION_UP) {


                log.debug(event.getDownTime() + " " + event.getEventTime());
                MotionEvent newEvent = MotionEvent.obtain(event.getDownTime(), event.getDownTime() + 499, event.getAction(), event.getX(), event.getY(), event.getMetaState());
                view.dispatchTouchEvent(newEvent);
                newEvent.recycle();
                return true;
            } 
            return false;
        }
    });

This actually appears to work, but not in all cases. It seems to work if I manage to not move my finger at all during the hold. However, if I do, it doesn't work. I suspect it has something to do with the ACTION_MASKED flag Android Press LongClickListener get X, Y Coordinates, OnTouchListener but tried a few things and couldn't seem to affect the outcome.

So, can either of these methods be made to work, or is there another way to replace the long touch click with a short touch click?

Community
  • 1
  • 1
s.field212
  • 75
  • 2
  • 11

2 Answers2

0

Turning long clicks into regular clicks will confuse the user, usually they expect it to get cancelled with a long click.

So you should either disable it with Java or with CSS.

Java

First enable long click setLongClickable(true); then the setOnLongClickListener, and then you can return a click:

webview.setLongClickable(true);
webview.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        return true;
        }
});

or

CSS

And to disable text selection add this CSS:

body {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

Check the Mozilla documentation here.

sharshi
  • 963
  • 11
  • 16
  • Thanks for the answer. I would normally agree, but this is not a webview in the classic sense. It's mimicking a native app entirely, and the webview side only comes from a desire to make the displayed local web page work on multiple platforms. I had made the question because at that point I had limited ability to change the js powered page, and so was searching for a java way to do this (the js was not recognizing the long clicks at all, even when passed as in your example). In the end we went with the zepto javascript library to handle it. I should update the question. – s.field212 Jan 14 '14 at 21:32
0

In the end, we used the zepto javascript library http://zeptojs.com/ to solve the problem, which handles interpreting the various long/move/short click events that occur from the user. That way we could just put js event handlers for each type and explicitly call appropriate methods.

s.field212
  • 75
  • 2
  • 11