Странный просчет при попытке определить, прокручивается ли WebView вниз

У меня проблема с обнаружением, когда WebView прокручивается вниз. Я использую следующий код:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);

    int bottom = ((int) Math.floor(getContentHeight() * getScale()) - getHeight());
    MyLogger.log(y + "____" + bottom);

    if (y == bottom) {
        // Trigger listener
    }
}

Ведение журнала дает мне следующий вывод:

162____164

Так или иначе, здесь есть просчет в 2 пикселя, и я понятия не имею, откуда это происходит.

Благодарю.

2 ответа

Решение

Расчет, который вы там делаете, кажется правильным. Это было бы лучше выразить как:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);
    final int DIRECTION_UP = 1;
    if (!canScrollVertically(DIRECTION_UP)) {
        // Trigger listener.
    }
}

Есть пара случаев, когда вы не сможете обнаружить, что находитесь внизу страницы таким образом:

  • Если страница обрабатывает прокрутку с помощью сенсорных обработчиков, а pageScale() больше 1.0. В этом случае 'bottom' обнаруживается в координатном пространстве CSS и из-за округления может не всегда корректно отображаться в координатное пространство android.view.View (хотя это должно быть исправлено в KitKat).
  • Вы или используемая вами библиотека переопределяете WebView.scrollTo/overScrollBy/ и т.д.. чтобы не допустить прокрутки до самого конца.

В качестве последнего обходного пути вы можете переопределить onOverScrolled:

@Override
protected void onOverScrolled (int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    if (scrollY > 0 && clampedY && !startedOverScrollingY) {
        startedOverScrollingY = true;
        // Trigger listener.
    }
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);
    if (y < oldY) startedOverScrollingY = false;
}

Если это воспроизводится в новейшей версии Android, не могли бы вы подать отчет об ошибке. Идеально создать минималистичное приложение, которое воспроизводит проблему с пустой (или тривиальной) страницей.

Получил точный результат со следующим:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);

    if (y == computeVerticalScrollRange() - getHeight()) {
        // Trigger listener
    }
}
Другие вопросы по тегам