我有一个使用内置缩放控件的webview,如下所示:
wv = new WebView(this);
wv.getSettings().setBuiltInZoomControls(true);
注意:这会激活两个主要功能 - 捏合缩放和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小部件的问题
我是否错过了一些允许他们共存的重要代码,或者我只需要选择一个我可以不用的代码?
答案 0 :(得分:3)
因此,在遇到同样的问题后,我试图理解其中一些答案无济于事。手头的问题是,一旦用户调用滚动(不是缩放缩放)(至少对我来说......),WebView实例就会丢失其OnTouchListener引用。我怎么知道这个?嗯......
Webview从View继承dispatchTouchEvent()。 dispatchTouchEvent调用onTouch()(这是不应该触发的函数)
正如我之前所说,onTouch()未被调用的原因是WebView实例的OnTouchListener由于某种原因被设置为null。这可以通过在View的dispatchTouchEvent()方法
中放置一个断点来看出所以为了解决这个问题,我们像这样扩展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也会启动答案 1 :(得分:2)
我有同样的问题,但设法通过在扩展的WebView类中再次设置监听器来解决它:
public void invalidate() {
super.invalidate();
setOnTouchListener(this);
}
不幸的是,现在我遇到了相反的问题,即缩放控件(加/减小部件)不再接收触摸事件。在使用OnTouchListener和缩放之间似乎存在一些排他性,至少在Android SDK等级8(Froyo 2.2)中。
这对我来说听起来像个错误,但是很想找到解决方法。
答案 2 :(得分:2)
尝试
youWebView.getSettings().setBuiltInZoomControls(false);
这对我有用。
答案 3 :(得分:1)
一个肮脏的解决方案是覆盖Web视图顶部的隐形视图并检测其中的触摸,您必须区分是否消耗了触摸,或者返回false以将触摸传递给底层Web视图。
答案 4 :(得分:1)
解决方法非常简单。 您必须创建一个自定义类,它扩展了一个ViewGroup子类,如LinearLayout。然后重写onInterceptTouchEvent - 它将在ViewGroup子项的onTouchEvent之前调用。将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);
}
}
答案 5 :(得分:0)
这是我能找到解决这个问题的最接近的方法。我需要在触摸时将输入焦点设置为WebView。我能做到的唯一方法是扩展WebView并覆盖onTouchEvent函数。即使在WebView中使用了Zooming,也会调用此函数。
public class NewWebView extends WebView {
public NewWebView(Context context) {
super(context);
}
public NewWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public NewWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean consumed = super.onTouchEvent(ev);
if (isClickable())
if (ev.getAction() == MotionEvent.ACTION_DOWN)
{
if (!hasFocus())
requestFocus();
}
return consumed;
}
不要忘记,如果您使用XML来创建布局,则需要将“WebView”更改为完全限定的packagename.NewWebView(否则,如果您尝试执行以下操作,则会出现令人困惑的ClassCastException:
webView = (NewWebView) findViewById(R.id.new_web_view);
答案 6 :(得分:0)
我认为有一些排他性,例如,对于500x500的网络视图,你将它放大到1000x1000,然后你触及它,现在应该报告什么位置?
但我真的需要让他们一起工作。
答案 7 :(得分:0)
我遇到类似的问题,在使用捏缩放之后,onTouch
无法调用。受 jpeskin 的回答启发,这段代码对我有用(将它添加到扩展WebView的类中):
@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 touchListener.onTouch(v, event);
}
touchListener
的类型为android.view.View.OnTouchListener
。
答案 8 :(得分:0)
我和Stijn.V有相同的缩放问题。我在他的回答中使用了代码,但仍然有一个问题,touchListener有时被设置为null。这是我的完整webview课程,在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);
}
});
答案 9 :(得分:0)
我遇到了同样的问题,我扩展了WebView并创建了自己的ontouchlistener来避免这个bug。例如: 公共类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;
}
}
答案 10 :(得分:0)
对我来说效果很好。只需使用onTouchEvent(MotionEvent事件)而不是onTouch(View v,MotionEvent事件)。即使setBuiltInZoomControls设置为true也可以工作。