Android 安卓:ZoomPicker打破了传统的监听模式
我有一个webview,它使用内置的缩放控件,如下所示:Android 安卓:ZoomPicker打破了传统的监听模式,android,webview,zooming,ontouchlistener,Android,Webview,Zooming,Ontouchlistener,我有一个webview,它使用内置的缩放控件,如下所示: wv = new WebView(this); wv.getSettings().setBuiltInZoomControls(true); wv.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { wv.invokeZoomPicker(); L
wv = new WebView(this);
wv.getSettings().setBuiltInZoomControls(true);
wv.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
wv.invokeZoomPicker();
Log.i("touch", "touched!");
return false;
}
});
注意:这将激活两个主要功能-pinch to zoom和invokeZoomPicker()(后者仅在视图上执行滑动操作时调用,简单的触摸无法启用)
我还希望在触摸事件发生时发生以下情况
wv.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Log.i("touch", "touched!");
return false;
}
});
当WebView加载时,我点击屏幕,每次我与屏幕交互时,日志都会显示“触动”,正如预期的那样。但是,如果我做了一些会触发invokeZoomPicker()的操作(只要zoom小部件不出现,收缩到缩放似乎不会导致此问题),onTouchListener将停止响应我的点击(即使在几秒钟后,当小部件从视图中消失时)
为了确保它是invokeZoomPicker(),我对代码的第二段进行了如下编辑:
wv = new WebView(this);
wv.getSettings().setBuiltInZoomControls(true);
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小部件肯定有问题
我是否错过了一些允许它们共存的关键代码,还是我只需要选择一个我可以不使用的代码?这是我最接近于解决这个问题的方法。我需要在触摸WebView时将输入焦点设置为WebView。我能做到这一点的唯一方法是扩展WebView并重写onTouchEvent函数。即使在WebView中使用了缩放,也会调用此函数
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);
我也遇到了同样的问题,但通过在扩展WebView类中再次设置侦听器,我成功地解决了这个问题:
public void invalidate() {
super.invalidate();
setOnTouchListener(this);
}
不幸的是,现在我遇到了相反的问题,缩放控件(加减小部件)不再接收触摸事件。至少在Android SDK级别8(Froyo 2.2)中,OnTouchListener和zoom之间似乎存在某种排他性
对我来说这听起来像一个bug,但我很想找到一个解决办法。我认为有一些排他性,例如,对于500x500的web视图,您将其放大到1000x1000,然后您触及它,现在它应该报告什么位置
但我真的需要让他们一起工作。一个肮脏的解决方案是在web视图顶部覆盖一个不可见的视图,并在那里检测触摸,您必须区分触摸是否被使用,或者返回false以将触摸传递到基础web视图。解决方法非常简单。 您必须创建一个自定义类,该类扩展了一个ViewGroup子类,如LinearLayout。然后重写onInterceptTouchEvent-它将在ViewGroup子级的onTouchEvent之前调用。将webview控件放入自定义ViewGroup子类中,然后将其插入到活动的视图层次结构中,这样做并不十分优雅红色,但是-它有效。
我遇到了一个类似的问题,
onTouch
在我使用pinch缩放后不会被调用。受jpeskin答案的启发,这段代码对我很有用(将其添加到扩展WebView的类中):
更新:
@Override
public boolean onTouch(View v, MotionEvent event) {
return touchListener.onTouch(v, event);
}
touchListener
属于android.view.view.OnTouchListener类型。我与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);
}
});
试一试
这对我来说很有用。我遇到了同样的问题,我扩展了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;
}
}因此,在我自己遇到同样的问题后,我试图理解其中的一些答案,但没有任何效果。目前的问题是,一旦用户调用scroll(而不是pinch zoom)(至少对我来说…),WebView实例将丢失其OnTouchListener引用。我是如何解决的?嗯 Webview从视图继承dispatchTouchEvent()。 dispatchTouchEvent调用onTouch() 正如我前面所说,onTouch()没有被调用的原因是WebView实例的OnTouchListener由于某种原因被设置为null 为了解决这个问题,我们对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现在即使在缩放或滚动后也会启动对我来说效果非常好。只需使用onTouchEvent(MotionEvent事件)而不是OnTouch(View v,MotionEvent事件)。即使SetBuilTinZoomControl设置为true也能工作。我也遇到了同样的问题。您是否找到了解决方案?不幸的是,我还没有找到解决方案。很抱歉,我没有更早地找到它,但我终于有机会测试此代码,不幸的是,此方法无法再次工作。您的代码没有在中为我编译一个扩展WebView的类——它说onTouch方法未定义。您自己在WebView子类中实现了onTouch方法吗?如果是这样,您的示例将更清晰,用注释代替onTouch()调用。我已经检查了它,我确实有一个
onTouch()扩展WebView类中的
方法,因此类实现了OnTouchListener
。这对我来说非常有效。我只是制作了一个
,并将其放置在
内部的
上。然后我将视图的设置为OnTouchListener
,并使其返回false
。
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;
}
}