Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
465 views
in Technique[技术] by (71.8m points)

webview - android: ZoomPicker breaks onTouchListener

I've got a webview which makes use of the built in zoom controls, as follows:

wv = new WebView(this);
wv.getSettings().setBuiltInZoomControls(true);

Note: this activates two main functions - pinch-to-zoom and invokeZoomPicker() (the latter is only called when a swiping action is done on the view, a simple touch doesn't enable it)


and i also want things to happen when touch events occur, using the following

wv.setOnTouchListener(new View.OnTouchListener() {  
    public boolean onTouch(View v, MotionEvent event) {
        Log.i("touch", "touched!");
        return false;
    }
});

When the WebView loads, and I tap the screen, the log states "touched" every time I interact with the screen, as expected. However, if I do something that would set off invokeZoomPicker() (pinch to zoom doesn't seem to cause this problem, as long as the zoom widget doesn't appear), onTouchListener stops responding to my taps (even after a few seconds, when the widget disappears from view).

To make sure it was invokeZoomPicker(), I edited the second segment of my code as follows:

wv.setOnTouchListener(new View.OnTouchListener() {  
    public boolean onTouch(View v, MotionEvent event) {
        wv.invokeZoomPicker();
        Log.i("touch", "touched!");
        return false;
    }
});

This new onTouch method now only triggers once (as a result of which the zoomwidget appears on the view - and disappears a few seconds later), and then the onTouch method doesn't get called again until the view is reloaded - so it is definitely a problem with the invokeZoomPicker()/Zoom widget

Have I missed some vital piece of code that allows them to coexist, or do I just have to choose which one I can live without?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So after running into the same problem myself, I tried to make sense of some of these answers to no avail. The problem at hand is that once the user invokes scroll (not pinch-zoom) (at least for me...), the WebView instance loses its OnTouchListener reference. How did I figure this out? Well...

Webview inherits dispatchTouchEvent() from View. dispatchTouchEvent calls onTouch() (which is the function not firing that should)

The reason why onTouch() wasn't getting called was, as I said before, that the WebView instance's OnTouchListener was getting set to null for some reason. This can be seen by putting a breakpoint in View's dispatchTouchEvent() method

So to solve this, we extend WebView like so:

import android.content.Context;
import android.util.AttributeSet;
import android.webkit.WebView;

public class TouchWebView extends WebView {

    WebTouchListener wtl;

    public TouchWebView(Context context) {
        super(context);
    }

    public TouchWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public TouchWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void resetTouchListener() {

        if(this.wtl == null) {
            this.wtl = new WebTouchListener();
        }
        this.setOnTouchListener(wtl);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        this.resetTouchListener();
        return super.dispatchTouchEvent(event);
    }
}

And then we implement our OnTouchListener:

import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.webkit.WebView;

public class WebTouchListener implements OnTouchListener {

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        WebView.HitTestResult hr = ((TouchWebView)v).getHitTestResult();
        //Log.i(TAG, "getExtra = "+ hr.getExtra() + " Type=" + hr.getType());

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            System.out.println(hr.getExtra() + " " + hr.getType());
        }

        // TODO Auto-generated method stub
        return false;
    }


}

OnTouch will now fire even after zooming or scrolling


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...