Что такое VerticalScrollExtent в Android ScrollView?

из ответа на один из других моих вопросов я нашел Google демо подкласса ListView это позволяет изменить порядок элементов.

демка работает отлично, но у меня возникли некоторые проблемы, чтобы понять, как это работает: Когда элемент перетаскивается выше / ниже границ ListView, ListView начинает прокрутку вверх / вниз, чтобы открыть новые элементы. Необходимые определения различных параметров базового Функцией ScrollView:

public boolean handleMobileCellScroll(Rect r) {         
    int offset = computeVerticalScrollOffset();
    int height = getHeight();
    int extent = computeVerticalScrollExtent();
    int range = computeVerticalScrollRange();
    int hoverViewTop = r.top;
    int hoverHeight = r.height();       

    if (hoverViewTop <= 0 && offset > 0) {
        smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
        return true;
    }

    if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
        smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
        return true;
    }

    return false;
}
  • height - это высота самого ListView
  • offsetположение прокрутки = сколько единиц / пикселей было прокручено вверх / вниз
  • range - это высота полного содержимого.
  • extent - Ну, что это?

ListView наследует computeVerticalScrollExtent() С View и Доку говорит:

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

если посмотреть на код computeVerticalScrollExtent() не реализован один из sublasses, но только напрямую по View: он просто возвращает высоту просмотра.

это имеет смысл: если ListView / ScrollView имеет высоту 500, часть содержимого прокрутки, которая видна в то время также 500. Это смысл ScrollExtent? почему ScrollExtent необходимо? Почему бы просто не использовать getHeight() напрямую?

Я думаю, что мне чего-то не хватает, и я рад любому намеку!

3 ответов


уже поздно, но надеюсь, все в порядке.

1) метод фактически реализуется подклассами. Например, этой это то, что он выглядит для AbsListView (ListViewС суперклассом).
2) Viewвысота может отличаться от высоты вертикальной прокрутки-просто представьте себе View со странной верхней / нижней прокладкой .

эти два момента в значительной степени делают другие вопросы неактуальными :)


  • вычислить * ScrollOffset - определяет расстояние между началом прокручиваемой области и верхней части текущего окна просмотра внутри прокручиваемой области. Так, например, если в вашем списке 10 элементов, и вы прокрутили вниз, так что 3-й элемент находится в самом верхнем видимом элементе, то смещение равно 3 (или 3*itemHeight, см. ниже).

  • вычислить * ScrollExtent - определяет размер текущего окна просмотра внутри прокручивать область. Так, например, если в вашем списке есть 10 элементов, и вы можете увидеть 5 из этих элементов, то экстент равен 5 (или 5 * itemHeight, см. ниже).

  • вычислить * ScrollRange - определяет размер области прокрутки. Например, если в вашем списке 10 элементов, диапазон равен 10 (или 10*itemHeight, см. ниже).

обратите внимание, что все эти методы могут возвращать значения в различных единицах в зависимости от их реализации, поэтому для в приведенных выше примерах я использую индексы, но в некоторых случаях эти методы вернут значения пикселей, эквивалентные ширине или высоте элементов.

в частности, LinearLayoutManager RecyclerView будет возвращать индексы, если включена функция "гладкая полоса прокрутки", иначе она будет возвращать значения пикселей. См.ScrollbarHelper в библиотеке поддержки для получения дополнительной информации.

дополнительные материалы для чтения: https://groups.google.com/forum#!тема / android-разработчики/Hxe-bjtQVvk


Это пример кода, который может помочь вам понять, как получить полосу прокрутки сверху и снизу с помощью computeVerticalScrollExtent:

scrollbarTop = (float)this.computeVerticalScrollExtent()/this.computeVerticalScrollRange()*this‌​.computeVerticalScrollOffset(); 

scrollbarBottom = (float)this.computeVerticalScrollExtent()/this.computeVerticalScrollRange()*(thi‌​s.computeVerticalScrollExtent()+this.computeVerticalScrollOffset());