Android: ZoomPicker ломается на TouchListener - PullRequest
9 голосов
/ 25 декабря 2010

У меня есть веб-просмотр, в котором используются встроенные элементы управления масштабированием:

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

Примечание: активируются две основные функции - pinch-to-zoom и invokeZoomPicker () (последняя вызывается только тогда, когда на представлении выполняется действие смахивания, простое касание не активирует его)


и я также хочу, чтобы что-то происходило, когда происходят события касания, используя следующее

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

Когда WebView загружается, и я нажимаю на экран, состояния журнала «соприкасаются» каждый раз, когда я взаимодействую с экраном, как и ожидалось. Тем не менее, если я сделаю что-то, что отключит invokeZoomPicker () (кажется, что увеличение масштаба не вызывает этой проблемы, пока виджет масштабирования не появляется), onTouchListener перестает отвечать на мои нажатия (даже через несколько секунд , когда виджет исчезает из поля зрения).

Чтобы убедиться, что это был invokeZoomPicker (), я отредактировал второй сегмент моего кода следующим образом:

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

Этот новый метод onTouch теперь срабатывает только один раз (в результате чего zoomwidget появляется в представлении - и исчезает через несколько секунд), а затем метод onTouch не вызывается снова, пока представление не будет перезагружено, поэтому это определенно проблема с виджетом invokeZoomPicker () / Zoom

Я пропустил какой-то жизненно важный кусок кода, который позволяет им сосуществовать, или мне просто нужно выбрать, без чего я могу жить?

Ответы [ 11 ]

3 голосов
/ 17 января 2014

Поэтому, столкнувшись с той же самой проблемой, я попытался разобраться в некоторых из этих ответов, но безрезультатно.Проблема в том, что, как только пользователь вызывает прокрутку (не пинч-зум) (по крайней мере, для меня ...), экземпляр WebView теряет свою ссылку OnTouchListener.Как я понял это?Ну ...

Webview наследует dispatchTouchEvent () от View.dispatchTouchEvent вызывает onTouch () (это функция, которая не запускается, что должно)

Причина, по которой onTouch () не вызывается, заключается в том, как я уже говорил ранее, что OnTouchListener экземпляра WebView получает нулевое значение длянекоторая причина.Это можно увидеть, поместив точку останова в метод dispatchTouchEvent () View

. Чтобы решить эту проблему, мы расширяем WebView следующим образом:

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);
    }
}

И затем мы реализуем наш 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() + "\t\t Type=" + hr.getType());

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

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


}

OnTouch теперь будет срабатывать даже после увеличения или прокрутки

2 голосов
/ 16 августа 2013

Попробуйте

youWebView.getSettings().setBuiltInZoomControls(false);

Это работа для меня.

2 голосов
/ 25 марта 2011

У меня была та же проблема, но мне удалось ее решить, снова настроив слушателя в моем расширенном классе WebView:

public void invalidate() {
    super.invalidate();
    setOnTouchListener(this);
}

К сожалению, теперь у меня есть противоположная проблема в том, что элементы управления масштабированием/ минус виджет) больше не получает сенсорные события.Кажется, есть некоторая исключительность между наличием OnTouchListener и zoom, по крайней мере, в Android SDK level 8 (Froyo 2.2).

Для меня это звучит как ошибка, но я бы хотел найти обходной путь.

1 голос
/ 30 июля 2011

Обходной путь довольно прост.Вы должны создать пользовательский класс, который расширяет один из подклассов ViewGroup, например LinearLayout.Затем переопределите onInterceptTouchEvent - он будет вызываться до onTouchEvent дочернего элемента ViewGroup.Не очень элегантно поместить элемент управления webview в пользовательский подкласс ViewGroup, а затем вставить его в иерархию представления активности - где это желательно, но - это работает.

private class OwnedLayout extends LinearLayout
{
    protected OwnedLayout(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    protected OwnedLayout(Context context)
    {
        super(context);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev)
    {
        //Put Your code here
        return super.onInterceptTouchEvent(ev);
    }


}
1 голос
/ 17 мая 2011

Грязное решение состоит в том, чтобы закрыть невидимый вид сверху вашего веб-вида и обнаружить там касания, и вы должны различать, используется ли касание, или возвращать false, чтобы передавать касания в базовый веб-вид.

0 голосов
/ 01 июня 2016

прекрасно работает для меня. Просто используйте onTouchEvent (событие MotionEvent) вместо onTouch (View v, событие MotionEvent). Работает, даже если для setBuiltInZoomControls установлено значение true.

0 голосов
/ 03 октября 2013

Я столкнулся с той же проблемой, и я расширил WebView и создал свой собственный ontouchlistener, чтобы избежать этой ошибки. Например: открытый класс BookknowWebView расширяет WebView {

private GestureDetector gestureDetector;
    private OnTouchListener mListener;

/**
 * @param context
 * @param attrs
 * @param defStyle
 */
public BookknowWebView(Context context) {
    super(context);
}

/**
 * @param context
 * @param attrs
 * @param defStyle
 */
public BookknowWebView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

/**
 * @param context
 * @param attrs
 * @param defStyle
 */
public BookknowWebView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public void setBookknowOnTouchListener(OnTouchListener l){
    mListener = l;
}

/* 
 * @see android.webkit.WebView#onTouchEvent(android.view.MotionEvent)
 */
@Override
public boolean onTouchEvent(MotionEvent ev) {
     mListener.onTouch(this, ev);       
    return gestureDetector.onTouchEvent(ev) || super.onTouchEvent(ev);
}

public void setGestureDetector(GestureDetector gestureDetector) {
    this.gestureDetector = gestureDetector;
}   

}

0 голосов
/ 05 августа 2013

У меня была та же проблема с масштабированием, что и у Stijn.V. Я использовал код в его ответе, но все еще имел проблему с touchListener, иногда установленным в нуль. Вот мой полный класс веб-просмотра, протестированный на Android 4.0 - 4.3

public class BookWebView extends WebView implements OnTouchListener {

private OnTouchListener mTouchListener;

public BookWebView(Context context) {
    super(context);

}

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

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

@Override
public boolean onTouchEvent(MotionEvent event) {            
    boolean consumed = super.onTouchEvent(event);               
    onTouch(this, event);           
    return consumed;
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    return mTouchListener.onTouch(v, event);
}

@Override
public void setOnTouchListener(OnTouchListener l) {
    super.setOnTouchListener(l);
    if(l != null){
        mTouchListener = l;
    }
}

}

Ради полноты вот как инициализируется touchEvent в моей деятельности по вызову

bookWebview.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return mGestureDetector.onTouchEvent(event);
        }
    });
0 голосов
/ 24 августа 2011

У меня была похожая проблема, когда onTouch не вызывали после того, как я использовал пинч для увеличения .Вдохновленный ответом jpeskin , этот код работал для меня (добавьте его в класс, расширяющий WebView):

@Override
public boolean onTouchEvent(MotionEvent event) {            
    boolean consumed = super.onTouchEvent(event);               
    onTouch(this, event);           
    return consumed;
}

update:

@Override
public boolean onTouch(View v, MotionEvent event) {
    return touchListener.onTouch(v, event);
}

touchListener относится к типу android.view.View.OnTouchListener.

0 голосов
/ 17 мая 2011

Я думаю, что есть некоторая исключительность, например, для веб-просмотра 500x500, и вы увеличиваете его до 1000x1000, затем вы касаетесь его, теперь, какую позицию он должен сообщить?заставить их работать вместе.

...