web-dev-qa-db-ja.com

Android WebView JellyBean->発生しないはず:rect-based-testノードが見つかりません

私のアプリケーションは、ViewPagerによって保持されているフラグメントにある多くのWebビューを使用しています。

Jellybeanを搭載したGalaxy Nexusのアプリをスワイプするたびに、次のコンソールメッセージが何度も表示されます。

08-23 13:44:03.374: E/webcoreglue(21690): Should not happen: no rect-based-test nodes found

私が問題を解決できるように、誰がここで何が間違っているのか説明できますか?

47
Ostkontentitan

この問題は、WebViewが表示される四角形が変更されていることにWebViewが気付かないシナリオがあるため、Webkitが懸念する限り、ページがまだ表示されないために発生します。したがって、すべてのタッチはウィンドウの外に落ち、拒否されます。

最もクリーンな修正は、WebViewの可視性が変更されたことがわかっている場合(ビューページャーからのsetPrimaryItemコールバックへの応答など)、webview.onScrollChanged(webview.getScrollX(), webview.getScrollY());を呼び出します

保護されたonScrollChangedをパブリックメソッドにプロモートするには、webviewをサブクラス化する必要があります。

21
John Reck

私はこの正確な問題を抱えていました。問題はまさに、Rahul Doleが上記の答えで言ったことです。

私はこれに数日かけてさまざまなことを試みています。向きが変わると、目に見えるWebView onLongClickが再び機能することに気づいたので、この小さな宝石を思いつきました。確かに非常にハッキーですが、動作します!

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

私はまったく同じ問題に直面しました。私のアプリでは、jquery bind()で「touchend」を使用してコード化されたクリックイベントが発生していましたが、このエラーが発生し、クリック(タップ)に応答することはありませんでした。それで私はbind()で 'touchend'を 'click'に置き換えようとしましたが、うまくいきました!クリック(タップ)に応答し、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軸ベクトルを識別するためのものだと思います。

16
Rahul Dole

なぜ機能したのか、手がかりはありません。この問題を修正するために、onTouchEventリスナーをMainActivity.Javaに追加しました。

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

WebViewを含むJellyBeanおよびViewPager +フラグメントでも同じ問題が発生します。そして、同じコードがAndroid 2.2で実行されているので問題ありません。したがって、これはJB WebView実装のバグだと思います。

JBでは、WebViewで最初に表示されたフラグメントのみが正しく機能し、ログに「発生しないはずです」というエラーが発生せず、getHitTestResult()呼び出しは正しい値を返します。次のページにスワイプすると、ログにエラーが表示され、getHitTestResult()はゼロとヌルのみを返します。

空のコンテナでフラグメントを作成し、WebViewを作成し、それらを設定し、ViewPagerで現在のフラグメントがアクティブになったときにのみデータをロードするソリューションを1つだけ見つけました。この場合、WebViewは必要に応じて機能します。しかし、残念ながら、これはViewPagerでページをスムーズにスワイプするという考えを完全に破ります。

明日は、ViewPagerのフラグメントを複合ビューに置き換えようとします。チャンスはほとんどありませんが、結果が成功するかどうかをお知らせします。

1
Vlad Kuts

別の解決策:

それを修正するためにWebViewクラスを拡張する必要はありません。Webビューのコンテンツ(myWebView.loadUrl( "...")を読み込んだ直後に次の2行を追加することで修正しました。

wv.loadUrl("your url here");

//Add the following two lines
myWebView.scrollTo(myWebView.getScrollX(), myWebView.getScrollY()+1);
myWebView.scrollTo(myWebView.getScrollX(), myWebView.getScrollY()-1);

これが役立つことを願っています(私は自分でテストし、うまくいきました)。

乾杯

0
Ahmed

Cordova + Sencha Touch環境で働いていたときにも起こりました。 CordovaActivityにはonScrollChanged()メソッドのようなものがないため、上記のソリューションを適用できませんでした。

何時間も頭を壁にぶつけた後、これが完全にレンダリングされる前にWebインターフェースの一部が呼び出されたことを発見しました。私の場合、これらのメソッドはExt.PanelViewactivateイベントによってトリガーされました。そのイベントをpaintedに置き換えたので、それ以降はすべてが魅力のように機能します。

これはコピーペーストのソリューションではありませんが、誰かが調査の時間を節約するのに役立つことを願っています。

0
Adam Bubela