我的应用程序正在使用许多 webviews,这些 webviews 位于 ViewPager 持有的片段中。
每当我在带有 Jellybean 的 Galaxy Nexus 上滑动应用程序时,我都会一次又一次地收到以下控制台消息:
08-23 13:44:03.374: E/webcoreglue(21690): Should not happen: no rect-based-test nodes found
谁能向我解释这里出了什么问题,以便我能够解决这个问题?
我的应用程序正在使用许多 webviews,这些 webviews 位于 ViewPager 持有的片段中。
每当我在带有 Jellybean 的 Galaxy Nexus 上滑动应用程序时,我都会一次又一次地收到以下控制台消息:
08-23 13:44:03.374: E/webcoreglue(21690): Should not happen: no rect-based-test nodes found
谁能向我解释这里出了什么问题,以便我能够解决这个问题?
出现此问题是因为在某些情况下 WebView 无法注意到其可见矩形已更改,因此就 webkit 而言,页面仍然不可见。因此,所有触摸都落在窗口之外,并被拒绝。
最干净的解决方法是当您知道 WebView 的可见性已更改(例如响应来自 viewpager 的 setPrimaryItem 回调)时,调用webview.onScrollChanged(webview.getScrollX(), webview.getScrollY());
您需要将 webview 子类化以将受保护的 onScrollChanged 提升为公共方法。
我有这个确切的问题。问题正是 Rahul Dole 在上面的回答中所说的。
我花了几天时间尝试了很多不同的事情。我注意到当方向改变时,可见的 WebView onLongClick 再次工作......所以我想出了这个小宝石。确实它非常hacky,但它有效!
在扩展 WebView 的类中使用它:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
int temp_ScrollY = getScrollY();
scrollTo(getScrollX(), getScrollY() + 1);
scrollTo(getScrollX(), temp_ScrollY);
}
return super.onTouchEvent(event);
}
我遇到了完全相同的问题。在我的应用程序中,无论我在 jquery bind() 中使用 'touchend' 编码的点击事件,都会出现这个错误,并且它过去从不响应点击(点击)......并给人一种冻结的感觉。所以我只是尝试在bind()中用'click'替换'touchend',它成功了!响应点击(点击),也没有显示 webcoreglue 的日志条目..
我还在Android的webview代码中找到了这段代码..
HTMLElement* WebViewCore::retrieveElement(int x, int y,
const QualifiedName& tagName)
{
HitTestResult hitTestResult = m_mainFrame->eventHandler()
->hitTestResultAtPoint(IntPoint(x, y), false, false,
DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
IntSize(1, 1));
if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
LOGE("Should not happen: no in document Node found");
return 0;
}
const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
if (list.isEmpty()) {
LOGE("Should not happen: no rect-based-test nodes found");
return 0;
}
Node* node = hitTestResult.innerNode();
Node* element = node;
while (element && (!element->isElementNode()
|| !element->hasTagName(tagName))) {
element = element->parentNode();
}
DBG_NAV_LOGD("node=%p element=%p x=%d y=%d nodeName=%s tagName=%s", node,
element, x, y, node->nodeName().utf8().data(),
element ? ((Element*) element)->tagName().utf8().data() : "<none>");
return static_cast<WebCore::HTMLElement*>(element);
}
还有这个。。
// get the highlight rectangles for the touch point (x, y) with the slop
Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
{
Vector<IntRect> rects;
m_mousePos = IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(slop, slop));
if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
LOGE("Should not happen: no in document Node found");
return rects;
}
const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
if (list.isEmpty()) {
LOGE("Should not happen: no rect-based-test nodes found");
return rects;
}
//Rest of the part is omitted here...
注意到那里的日志消息了吗?我猜这段代码是用来识别在点击、点击或滑动时生成的 x 和 y 轴向量。.. </p>
JellyBean 和 ViewPager + 包含 WebViews 的片段有同样的问题。在 Android 2.2 上运行相同的代码一切正常,所以我认为这是 JB WebView 实现中的一个错误。
在 JB 上,只有第一个显示的带有 WebView 的片段可以正常工作,日志中没有错误“不应发生..”,并且 getHitTestResult() 调用返回正确的值。滑动到下一页,我在日志中有错误,getHitTestResult() 只返回零和空值。
现在我发现只有一种解决方案可以使用空容器创建片段并创建 WebView,设置它们并仅在当前片段在 ViewPager 中变为活动状态时加载数据。在这种情况下,WebView 根据需要工作。但是,不幸的是,这完全打破了在 ViewPager 中平滑滑动页面的想法。
有了最后一个想法,明天会尝试将ViewPager的fragment替换为复合视图。机会很小,但我会告诉你结果是否会成功。
不知道它为什么起作用。我在 MainActivity.java 中添加了 onTouchEvent 监听器来解决这个问题。
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
public class MyWebView extends WebView {
public MyWebView(Context context) {
super(context);
}
public MyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
onScrollChanged(getScrollX(), getScrollY(), getScrollX(), getScrollY());
return super.onTouchEvent(event);
}
}
当我在 Cordova + Sencha Touch 环境中工作时,它也发生在我身上。因为
CordovaActivity
没有类似的onScrollChanged()
方法,所以我无法应用上述任何解决方案。
经过数小时的头撞墙后,我发现在完全渲染之前已经调用了 Web 界面的某些部分。在我的情况下,这些方法是由activate
事件触发的Ext.PanelView
。我用那个事件代替了那个事件,painted
从那以后一切都像一个魅力。
虽然它不是复制粘贴解决方案,但我希望它可以帮助某人节省调查时间。
另一种解决方案:
你不需要扩展 WebView 类来解决这个问题。我通过在加载 Web 视图内容后添加以下两行来解决这个问题(myWebView.loadUrl(“...”):
wv.loadUrl("your url here");
//Add the following two lines
myWebView.scrollTo(myWebView.getScrollX(), myWebView.getScrollY()+1);
myWebView.scrollTo(myWebView.getScrollX(), myWebView.getScrollY()-1);
希望这会有所帮助(我测试了自己并且它有效)。
干杯
甚至我在 ViewPager 中有 WebView,并onTouchEvent()
通过扩展 webview 类来解决这个问题。
这是我的代码:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
requestFocusFromTouch();
}
return super.onTouchEvent(event);
}
干杯!!!